From deb795583e5ab253f33462e3e11e1df5eba6f598 Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Fri, 13 Jun 2025 16:27:22 +0200 Subject: [PATCH 01/30] Add a separate test case for each test file Signed-off-by: Robert Winkler --- xls/modules/zstd/BUILD | 2 +- xls/modules/zstd/zstd_dec_test.x | 169 ++++++++++++++++++++++++++++--- 2 files changed, 156 insertions(+), 15 deletions(-) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index fcd076ae01..8567aba4f1 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -1475,7 +1475,7 @@ xls_dslx_library( xls_dslx_test( name = "zstd_dec_dslx_test", - size = "large", + size = "enormous", srcs = [ "data/comp_frame.x", "data/comp_frame_fse_comp.x", diff --git a/xls/modules/zstd/zstd_dec_test.x b/xls/modules/zstd/zstd_dec_test.x index 2db5105f38..854bfa06e2 100644 --- a/xls/modules/zstd/zstd_dec_test.x +++ b/xls/modules/zstd/zstd_dec_test.x @@ -28,10 +28,11 @@ import xls.modules.zstd.parallel_rams; import xls.modules.zstd.literals_buffer; import xls.modules.zstd.fse_table_creator; import xls.modules.zstd.ram_mux; -// import xls.modules.zstd.zstd_frame_testcases as comp_frame; -// import xls.modules.zstd.data.comp_frame_huffman as comp_frame; -// import xls.modules.zstd.data.comp_frame_fse_comp as comp_frame; -// import xls.modules.zstd.data.comp_frame_fse_repeated as comp_frame; + +import xls.modules.zstd.data.comp_frame_huffman; +import xls.modules.zstd.data.comp_frame_huffman_fse; +import xls.modules.zstd.data.comp_frame_fse_comp; +import xls.modules.zstd.data.comp_frame_fse_repeated; import xls.modules.zstd.data.comp_frame; const TEST_WINDOW_LOG_MAX = u32:30; @@ -153,8 +154,9 @@ fn csr_addr(c: zstd_dec::Csr) -> uN[TEST_AXI_ADDR_W] { (c as uN[TEST_AXI_ADDR_W]) << 3 } -#[test_proc] -proc ZstdDecoderTest { +type TestFrames = common::DataArray[1]; + +proc ZstdDecoderTester { type CsrAxiAr = axi::AxiAr; type CsrAxiR = axi::AxiR; type CsrAxiAw = axi::AxiAw; @@ -258,7 +260,8 @@ proc ZstdDecoderTest { type LitBufRamWrReq = ram::WriteReq; type LitBufRamWrResp = ram::WriteResp; - terminator: chan out; + start_r: chan<()> in; + finished_s: chan<()> out; csr_axi_aw_s: chan out; csr_axi_w_s: chan out; @@ -318,7 +321,7 @@ proc ZstdDecoderTest { init {} - config(terminator: chan out) { + config(start_r: chan<()> in, finished_s: chan<()> out) { let (csr_axi_aw_s, csr_axi_aw_r) = chan("csr_axi_aw"); let (csr_axi_w_s, csr_axi_w_r) = chan("csr_axi_w"); @@ -702,7 +705,7 @@ proc ZstdDecoderTest { >(raw_axi_ar_r, raw_axi_r_s, raw_ram_rd_req_s, raw_ram_rd_resp_r); ( - terminator, + start_r, finished_s, csr_axi_aw_s, csr_axi_w_s, csr_axi_b_r, csr_axi_ar_s, csr_axi_r_r, fh_axi_ar_r, fh_axi_r_s, fh_ram_wr_req_s, fh_ram_wr_resp_r, bh_axi_ar_r, bh_axi_r_s, bh_ram_wr_req_s, bh_ram_wr_resp_r, @@ -721,10 +724,12 @@ proc ZstdDecoderTest { } next (state: ()) { + let tok = join(); + let (tok, _) = recv(tok, start_r); + trace_fmt!("Test start"); - let frames_count = array_size(comp_frame::FRAMES); + let frames_count = array_size(FRAMES); - let tok = join(); // FILL THE LL DEFAULT RAM trace_fmt!("Filling LL default FSE table"); @@ -779,7 +784,7 @@ proc ZstdDecoderTest { let tok = unroll_for! (test_i, tok): (u32, token) in u32:0..frames_count { trace_fmt!("Loading testcase {:x}", test_i + u32:1); - let frame = comp_frame::FRAMES[test_i]; + let frame = FRAMES[test_i]; let tok = for (i, tok): (u32, token) in u32:0..frame.array_length { let req = RamWrReq { addr: i as uN[TEST_RAM_ADDR_W], @@ -839,7 +844,7 @@ proc ZstdDecoderTest { }); let (tok, _) = recv(tok, csr_axi_b_r); - let decomp_frame = comp_frame::DECOMPRESSED_FRAMES[test_i]; + let decomp_frame = DECOMPRESSED_FRAMES[test_i]; // Test ZstdDecoder memory output interface // Mock the output memory buffer as a DSLX array // It is required to handle AXI write transactions and to write the incoming data to @@ -858,7 +863,7 @@ proc ZstdDecoderTest { // The maximal number if beats in AXI burst transaction let MAX_AXI_TRANSFERS = u32:256; // Actual size of decompressed payload for current test - let DECOMPRESSED_BYTES = comp_frame::DECOMPRESSED_FRAMES[test_i].length; + let DECOMPRESSED_BYTES = DECOMPRESSED_FRAMES[test_i].length; trace_fmt!("ZstdDecTest: Start receiving output"); let (tok, final_output_memory, final_output_memory_id, final_transfered_bytes) = for (axi_transaction, (tok, output_memory, output_memory_id, transfered_bytes)): @@ -913,6 +918,142 @@ proc ZstdDecoderTest { tok }(tok); + send(tok, finished_s, ()); + } +} + +#[test_proc] +proc RawLiteralsPredefinedSequencesTest { + terminator: chan out; + start_s: chan<()> out; + finished_r: chan<()> in; + + init {} + + config (terminator: chan out,) { + const FRAMES = comp_frame::FRAMES; + const DECOMPRESSED_FRAMES = comp_frame::DECOMPRESSED_FRAMES; + + let (start_s, start_r) = chan<()>("start"); + let (finished_s, finished_r) = chan<()>("finished"); + + spawn ZstdDecoderTester(start_r, finished_s); + (terminator, start_s, finished_r) + } + + next(state: ()) { + let tok = send(join(), start_s, ()); + let (tok, _) = recv(tok, finished_r); + send(tok, terminator, true); + } +} + +#[test_proc] +proc RleLiteralsRepeatedSequencesTest { + terminator: chan out; + start_s: chan<()> out; + finished_r: chan<()> in; + + init {} + + config (terminator: chan out,) { + + const FRAMES = comp_frame_fse_repeated::FRAMES; + const DECOMPRESSED_FRAMES = comp_frame_fse_repeated::DECOMPRESSED_FRAMES; + + let (start_s, start_r) = chan<()>("start"); + let (finished_s, finished_r) = chan<()>("finished"); + + spawn ZstdDecoderTester(start_r, finished_s); + (terminator, start_s, finished_r) + } + + next(state: ()) { + let tok = send(join(), start_s, ()); + let (tok, _) = recv(tok, finished_r); + send(tok, terminator, true); + } +} + +// TODO: Tests with the `_skip` suffix are disabled in CI +// due to high memory usage. Re-enable them when the DSLX +// interpreter becomes more memory-efficient. + +#[test_proc] +proc RawHuffmanLiteralsPredefinedSequencesTest_skip { + terminator: chan out; + start_s: chan<()> out; + finished_r: chan<()> in; + + init {} + + config (terminator: chan out,) { + const FRAMES = comp_frame_huffman::FRAMES; + const DECOMPRESSED_FRAMES = comp_frame_huffman::DECOMPRESSED_FRAMES; + + let (start_s, start_r) = chan<()>("start"); + let (finished_s, finished_r) = chan<()>("finished"); + + spawn ZstdDecoderTester(start_r, finished_s); + (terminator, start_s, finished_r) + } + + next(state: ()) { + let tok = send(join(), start_s, ()); + let (tok, _) = recv(tok, finished_r); + send(tok, terminator, true); + } +} + +#[test_proc] +proc FseHuffmanLiteralsPredefinedSequencesTest_skip { + terminator: chan out; + start_s: chan<()> out; + finished_r: chan<()> in; + + init {} + + config (terminator: chan out,) { + const FRAMES = comp_frame_huffman_fse::FRAMES; + const DECOMPRESSED_FRAMES = comp_frame_huffman_fse::DECOMPRESSED_FRAMES; + + let (start_s, start_r) = chan<()>("start"); + let (finished_s, finished_r) = chan<()>("finished"); + + spawn ZstdDecoderTester(start_r, finished_s); + (terminator, start_s, finished_r) + } + + next(state: ()) { + let tok = send(join(), start_s, ()); + let (tok, _) = recv(tok, finished_r); + send(tok, terminator, true); + } +} + +#[test_proc] +proc RawHuffmanLiteralsCompressedSequencesTest_skip { + terminator: chan out; + start_s: chan<()> out; + finished_r: chan<()> in; + + init {} + + config (terminator: chan out,) { + + const FRAMES = comp_frame_fse_comp::FRAMES; + const DECOMPRESSED_FRAMES = comp_frame_fse_comp::DECOMPRESSED_FRAMES; + + let (start_s, start_r) = chan<()>("start"); + let (finished_s, finished_r) = chan<()>("finished"); + + spawn ZstdDecoderTester(start_r, finished_s); + (terminator, start_s, finished_r) + } + + next(state: ()) { + let tok = send(join(), start_s, ()); + let (tok, _) = recv(tok, finished_r); send(tok, terminator, true); } } From 120c3b8ef5c66453647c2a22c477341d0dd71bed Mon Sep 17 00:00:00 2001 From: Szymon Gizler Date: Fri, 23 May 2025 12:19:08 +0200 Subject: [PATCH 02/30] Add "pytype binary, library" hint --- xls/modules/zstd/BUILD | 1 + xls/modules/zstd/memory/BUILD | 1 + xls/modules/zstd/rtl/BUILD | 1 + 3 files changed, 3 insertions(+) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 8567aba4f1..0f23226ba6 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -14,6 +14,7 @@ # Build rules for XLS ZSTD codec implementation. +# pytype binary, library load("@rules_hdl//place_and_route:build_defs.bzl", "place_and_route") load("@rules_hdl//synthesis:build_defs.bzl", "benchmark_synth", "synthesize_rtl") load("@rules_hdl//verilog:providers.bzl", "verilog_library") diff --git a/xls/modules/zstd/memory/BUILD b/xls/modules/zstd/memory/BUILD index ba29c3a453..2f1cadae30 100644 --- a/xls/modules/zstd/memory/BUILD +++ b/xls/modules/zstd/memory/BUILD @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pytype binary, library load("@rules_hdl//place_and_route:build_defs.bzl", "place_and_route") load("@rules_hdl//synthesis:build_defs.bzl", "benchmark_synth", "synthesize_rtl") load("@rules_hdl//verilog:providers.bzl", "verilog_library") diff --git a/xls/modules/zstd/rtl/BUILD b/xls/modules/zstd/rtl/BUILD index 4447877821..64557ce107 100644 --- a/xls/modules/zstd/rtl/BUILD +++ b/xls/modules/zstd/rtl/BUILD @@ -23,6 +23,7 @@ The sources contain: """ +# pytype binary, library load("@rules_hdl//verilog:providers.bzl", "verilog_library") package( From 29ef8ce76dc750b70b2709a9f1f4ae99cbe02939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ob=C5=82onczek?= Date: Fri, 16 Aug 2024 14:19:45 +0200 Subject: [PATCH 03/30] Add cocotb tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add cocotb testing utilities: - XLSStruct for easier handling and serializing/deserializing XLS structs - XLSChannel that serves as a dummy receiving channel - XLSMonitor that monitors transactions on an XLS channel - XLSDriver that can send data on an XLS channel - LatencyScoreboard that can measure latency between corresponding transactions on input and output buses - File-backed AXI memory python model Add cocotb tests for: - modules/zstd/memory/MemReader - modules/zstd/memory/AxiWriter - modules/zstd/memory/MemWriter Co-authred-by: Pawel Czarnecki Co-authred-by: Robert Winkler Co-authred-by: Michal Czyz Signed-off-by: Michal Czyz Signed-off-by: Pawel Czarnecki Signed-off-by: Robert Winkler Signed-off-by: Krzysztof Obłonczek --- dependency_support/pip_requirements.in | 4 + dependency_support/pip_requirements_lock.txt | 70 +- xls/modules/zstd/cocotb/BUILD | 66 ++ xls/modules/zstd/cocotb/channel.py | 95 +++ xls/modules/zstd/cocotb/memory.py | 43 ++ xls/modules/zstd/cocotb/scoreboard.py | 69 ++ xls/modules/zstd/cocotb/utils.py | 57 ++ xls/modules/zstd/cocotb/xlsstruct.py | 175 +++++ xls/modules/zstd/memory/BUILD | 82 +++ .../zstd/memory/axi_writer_cocotb_test.py | 245 +++++++ xls/modules/zstd/memory/axi_writer_wrapper.v | 119 ++++ .../zstd/memory/mem_reader_cocotb_test.py | 271 +++++++ xls/modules/zstd/memory/mem_reader_wrapper.v | 111 +++ .../zstd/memory/mem_writer_cocotb_test.py | 667 ++++++++++++++++++ xls/modules/zstd/memory/mem_writer_wrapper.v | 193 +++++ 15 files changed, 2266 insertions(+), 1 deletion(-) create mode 100644 xls/modules/zstd/cocotb/BUILD create mode 100644 xls/modules/zstd/cocotb/channel.py create mode 100644 xls/modules/zstd/cocotb/memory.py create mode 100644 xls/modules/zstd/cocotb/scoreboard.py create mode 100644 xls/modules/zstd/cocotb/utils.py create mode 100644 xls/modules/zstd/cocotb/xlsstruct.py create mode 100644 xls/modules/zstd/memory/axi_writer_cocotb_test.py create mode 100644 xls/modules/zstd/memory/axi_writer_wrapper.v create mode 100644 xls/modules/zstd/memory/mem_reader_cocotb_test.py create mode 100644 xls/modules/zstd/memory/mem_reader_wrapper.v create mode 100644 xls/modules/zstd/memory/mem_writer_cocotb_test.py create mode 100644 xls/modules/zstd/memory/mem_writer_wrapper.v diff --git a/dependency_support/pip_requirements.in b/dependency_support/pip_requirements.in index 804306558e..ef46f4703a 100644 --- a/dependency_support/pip_requirements.in +++ b/dependency_support/pip_requirements.in @@ -13,6 +13,10 @@ pyyaml==6.0.1 # We build most of z3 ourselves but building python is really complicated. Just # use pypi version z3-solver==4.14.0.0 +pytest==8.2.2 +cocotb==1.9.0 +cocotbext-axi==0.1.24 +cocotb_bus==0.2.1 # Note: numpy and scipy version availability seems to differ between Ubuntu # versions that we want to support (e.g. 18.04 vs 20.04), so we accept a diff --git a/dependency_support/pip_requirements_lock.txt b/dependency_support/pip_requirements_lock.txt index dc895c7f19..9872e57406 100644 --- a/dependency_support/pip_requirements_lock.txt +++ b/dependency_support/pip_requirements_lock.txt @@ -14,6 +14,56 @@ click==8.1.3 \ # via # -r dependency_support/pip_requirements.in # flask +cocotb==1.9.0 \ + --hash=sha256:02a58ef6c941114964096e7c039bdd4e67e63816cfd2f6a9af6a34cd92b00e8e \ + --hash=sha256:0819794ef5e8fd14fee0b265933226cf600e85edc2f1a749b4d5f8fa2d31ce4e \ + --hash=sha256:0ba35617a677ff65a1273411a3dfdfc5f587128ad8cb9e941ab0eb17ec8fb3e2 \ + --hash=sha256:17556e3a23562f64d577d0eb117fe02e384aedee997b29497b5c395f5010ff82 \ + --hash=sha256:19b4e27b53a16e0b9c4cc5227c7f9d4dccac06e431a4f937e9f5513350196333 \ + --hash=sha256:1a0381ced5590a726032ba2265c6b70ac12cfb49edb152be86a081bb7d104751 \ + --hash=sha256:1aff68cf77059448a9a3278079037e34b50c8c2aee466d984295fa7fe699d390 \ + --hash=sha256:277281420fd6fc3002bb85d6bec497bd20ff3a3905d4b5f1301faf975f750ede \ + --hash=sha256:2daf743320331615f4e8ffb877ab0b04e6f913b911bb11bf9dbc1d876d9c4220 \ + --hash=sha256:2e9bcdbfba3e99c9297bd0d74ba781772d89d2c86e893980784ada252bd1a0f8 \ + --hash=sha256:3058c977f9d4e1f6333d505947f34b9142910719f1d8631c40a151dd86bad727 \ + --hash=sha256:5832d894419a9e8fe5c242e3ac86588e16e2cb379822dcb154bfec8544ae858e \ + --hash=sha256:598b841ed0809e5c64d8c383b8035f6ace5a6f9013f680cdc6981221911c005d \ + --hash=sha256:5a5c91027d7652aaf10e101743edd6b1e832039a19af75fca301275ef30f01d4 \ + --hash=sha256:61418f619af72c8cca8de622785b4f4bfc17ace09981de6eb44feae560cf3bbb \ + --hash=sha256:784c914c8df3fd79cfb148d2bcd17c4b2703c89af1278ed98773afb57ceea3e6 \ + --hash=sha256:87a19d3012f505ba7fda37483b851ef0ca40290ad8a9b28a820b84f8574287bb \ + --hash=sha256:89503f0749362d36b6fab8636710f1848943c21f9d488672921bac21e9edd29f \ + --hash=sha256:89e5189fd393918c27af2daefdcb13df4d52fa761f065d5964d2c4ff5c0642fb \ + --hash=sha256:8cb4b0edf8f0b47c3b604b461cb574fc75fd97efa893cbaf828f4f2f71cf459e \ + --hash=sha256:94e884e16186899ad5b4d131c3f7ff0a2277e67ea0660754e8810a4bbf2d610e \ + --hash=sha256:997dbca2a2cd933fd0a44d9fadeebc1e8a40701db15ea06f207811933dceb350 \ + --hash=sha256:a7cea13cb2fe4f5ca735490846342885117778a73008a67ed9cac667aaaf3f0d \ + --hash=sha256:a84edfbfa57dc6e16845a55feb0b4e1c8b6bbfa5ef1ab6768beba8d81e0546aa \ + --hash=sha256:a95b5e5708a3629d319d2b655d11345cc7e97fea9bdc9bc1df7435926ac30966 \ + --hash=sha256:aa6818c39ca1ce699e4bb1d84899c4f98c2d25c7671bd6c7beee3b1ee9d68834 \ + --hash=sha256:ab99bf7e055780b57419d4133fd4dca9c72a03b766a3e2200552f10498eb8845 \ + --hash=sha256:b966f5560a494fd99f95a1562f9326ca20c35bb118d4e6b50db41da8e4a6f718 \ + --hash=sha256:bc44a7708a5a63d3059a622c2fb90831dc33534c3343e971f5a6c78905097baa \ + --hash=sha256:c11e21d291ba2f889e33c21d76e9aec6ffdfb5666053dc34452666579daa675b \ + --hash=sha256:c848de13583478d71cc91e528e17c051ca6a3b92e89d703ac5015f17cab1287b \ + --hash=sha256:d944aa5509a0f0786d6f30554a2f8b1f229847f9ac9988879d7a05497739f668 \ + --hash=sha256:f50862153e1364f6edeaef9d70505093549fa097e9b2555ea46d1e4f94ac3287 \ + --hash=sha256:f74c598e230e1035103f6e3a97dd7a0e1bcacf7f3ea7481cd3bcde477b74e379 \ + --hash=sha256:fcb81c6c37e11b0729768dd8e192a9cfb809778699ab1fe89f4d92ba0beb3092 \ + --hash=sha256:ff2ddc8b304eb7076ceead2534a1b9828df771798fa9c2601ea983c86d23ec08 + # via + # -r dependency_support/pip_requirements.in + # cocotb-bus + # cocotbext-axi +cocotb-bus==0.2.1 \ + --hash=sha256:a197aa4b0e0ad28469c8877b41b3fb2ec0206da9f491b9276d1578ce6dd8aa8d + # via + # -r dependency_support/pip_requirements.in + # cocotbext-axi +cocotbext-axi==0.1.24 \ + --hash=sha256:3ed62dcaf9448833176826507c5bc5c346431c4846a731e409d87c862d960593 \ + --hash=sha256:533ba6c7503c6302bdb9ef86e43a549ad5da876eafb1adce23d39751c54cced4 + # via -r dependency_support/pip_requirements.in contourpy==1.3.1 \ --hash=sha256:041b640d4ec01922083645a94bb3b2e777e6b626788f4095cf21abbe266413c1 \ --hash=sha256:05e806338bfeaa006acbdeba0ad681a10be63b26e1b17317bfac3c5d98f36cda \ @@ -74,6 +124,10 @@ cycler==0.12.1 \ --hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 \ --hash=sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c # via matplotlib +find-libpython==0.4.0 \ + --hash=sha256:034a4253bd57da3408aefc59aeac1650150f6c1f42e10fdd31615cf1df0842e3 \ + --hash=sha256:46f9cdcd397ddb563b2d7592ded3796a41c1df5222443bd9d981721c906c03e6 + # via cocotb flask==2.3.2 \ --hash=sha256:77fd4e1249d8c9923de34907236b747ced06e5467ecac1a7bb7115ae0e9670b0 \ --hash=sha256:8c2f9abd47a9e8df7f0c3f091ce9497d011dc3b31effcf4c85a6e2b50f4114ef @@ -130,6 +184,10 @@ fonttools==4.55.8 \ --hash=sha256:f089e8da0990cfe2d67e81d9cf581ff372b48dc5acf2782701844211cd1f0eb3 \ --hash=sha256:f971aa5f50c22dc4b63a891503624ae2c77330429b34ead32f23c2260c5618cd # via matplotlib +iniconfig==2.0.0 \ + --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ + --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 + # via pytest itsdangerous==2.1.2 \ --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a @@ -346,7 +404,9 @@ numpy==1.24.4 \ packaging==24.2 \ --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f - # via matplotlib + # via + # matplotlib + # pytest pillow==11.1.0 \ --hash=sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83 \ --hash=sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96 \ @@ -420,6 +480,10 @@ pillow==11.1.0 \ --hash=sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9 \ --hash=sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761 # via matplotlib +pluggy==1.5.0 \ + --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ + --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 + # via pytest portpicker==1.3.1 \ --hash=sha256:d2cdc776873635ed421315c4d22e63280042456bbfa07397817e687b142b9667 # via -r dependency_support/pip_requirements.in @@ -440,6 +504,10 @@ pyparsing==3.2.1 \ --hash=sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1 \ --hash=sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a # via matplotlib +pytest==8.2.2 \ + --hash=sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343 \ + --hash=sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977 + # via -r dependency_support/pip_requirements.in python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 diff --git a/xls/modules/zstd/cocotb/BUILD b/xls/modules/zstd/cocotb/BUILD new file mode 100644 index 0000000000..23b1a843c3 --- /dev/null +++ b/xls/modules/zstd/cocotb/BUILD @@ -0,0 +1,66 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@xls_pip_deps//:requirements.bzl", "requirement") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//xls:xls_users"], + licenses = ["notice"], +) + +py_library( + name = "channel", + srcs = ["channel.py"], + deps = [ + ":xlsstruct", + requirement("cocotb"), + requirement("cocotb_bus"), + ], +) + +py_library( + name = "memory", + srcs = ["memory.py"], + deps = [ + requirement("cocotbext-axi"), + ], +) + +py_library( + name = "scoreboard", + srcs = ["scoreboard.py"], + deps = [ + ":channel", + ":xlsstruct", + requirement("cocotb"), + ], +) + +py_library( + name = "utils", + srcs = ["utils.py"], + deps = [ + requirement("cocotb"), + "//xls/common:runfiles", + ], +) + +py_library( + name = "xlsstruct", + srcs = ["xlsstruct.py"], + deps = [ + requirement("cocotb"), + ], +) diff --git a/xls/modules/zstd/cocotb/channel.py b/xls/modules/zstd/cocotb/channel.py new file mode 100644 index 0000000000..0970ab6e9b --- /dev/null +++ b/xls/modules/zstd/cocotb/channel.py @@ -0,0 +1,95 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any, Sequence, Type, Union + +import cocotb +from cocotb.handle import SimHandleBase +from cocotb.triggers import RisingEdge +from cocotb_bus.bus import Bus +from cocotb_bus.drivers import BusDriver +from cocotb_bus.monitors import BusMonitor + +from xls.modules.zstd.cocotb.xlsstruct import XLSStruct + +Transaction = Union[XLSStruct, Sequence[XLSStruct]] + +XLS_CHANNEL_SIGNALS = ["data", "rdy", "vld"] +XLS_CHANNEL_OPTIONAL_SIGNALS = [] + + +class XLSChannel(Bus): + _signals = XLS_CHANNEL_SIGNALS + _optional_signals = XLS_CHANNEL_OPTIONAL_SIGNALS + + def __init__(self, entity, name, clk, *, start_now=False, **kwargs: Any): + super().__init__(entity, name, self._signals, self._optional_signals, **kwargs) + self.clk = clk + if start_now: + self.start_recv_loop() + + @cocotb.coroutine + async def recv_channel(self): + """Cocotb coroutine that acts as a proc receiving data from a channel""" + self.rdy.setimmediatevalue(1) + while True: + await RisingEdge(self.clk) + + def start_recv_loop(self): + cocotb.start_soon(self.recv_channel()) + + +class XLSChannelDriver(BusDriver): + _signals = XLS_CHANNEL_SIGNALS + _optional_signals = XLS_CHANNEL_OPTIONAL_SIGNALS + + def __init__(self, entity: SimHandleBase, name: str, clock: SimHandleBase, **kwargs: Any): + BusDriver.__init__(self, entity, name, clock, **kwargs) + + self.bus.data.setimmediatevalue(0) + self.bus.vld.setimmediatevalue(0) + + async def _driver_send(self, transaction: Transaction, sync: bool = True, **kwargs: Any) -> None: + if sync: + await RisingEdge(self.clock) + + data_to_send = (transaction if isinstance(transaction, Sequence) else [transaction]) + + for word in data_to_send: + self.bus.vld.value = 1 + self.bus.data.value = word.binaryvalue + + while True: + await RisingEdge(self.clock) + if self.bus.rdy.value: + break + + self.bus.vld.value = 0 + + +class XLSChannelMonitor(BusMonitor): + _signals = XLS_CHANNEL_SIGNALS + _optional_signals = XLS_CHANNEL_OPTIONAL_SIGNALS + + def __init__(self, entity: SimHandleBase, name: str, clock: SimHandleBase, struct: Type[XLSStruct], **kwargs: Any): + BusMonitor.__init__(self, entity, name, clock, **kwargs) + self.struct = struct + + @cocotb.coroutine + async def _monitor_recv(self) -> None: + while True: + await RisingEdge(self.clock) + if self.bus.rdy.value and self.bus.vld.value: + vec = self.struct.from_int(self.bus.data.value.integer) + self._recv(vec) diff --git a/xls/modules/zstd/cocotb/memory.py b/xls/modules/zstd/cocotb/memory.py new file mode 100644 index 0000000000..52e512e053 --- /dev/null +++ b/xls/modules/zstd/cocotb/memory.py @@ -0,0 +1,43 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from cocotbext.axi.axi_ram import AxiRam, AxiRamRead, AxiRamWrite +from cocotbext.axi.sparse_memory import SparseMemory + + +def init_axi_mem(path: os.PathLike, kwargs): + with open(path, "rb") as f: + sparse_mem = SparseMemory(size=kwargs["size"]) + sparse_mem.write(0x0, f.read()) + kwargs["mem"] = sparse_mem + + +class AxiRamReadFromFile(AxiRamRead): + def __init__(self, *args, path: os.PathLike, **kwargs): + init_axi_mem(path, kwargs) + super().__init__(*args, **kwargs) + + +class AxiRamFromFile(AxiRam): + def __init__(self, *args, path: os.PathLike, **kwargs): + init_axi_mem(path, kwargs) + super().__init__(*args, **kwargs) + + +class AxiRamWriteFromFile(AxiRamWrite): + def __init__(self, *args, path: os.PathLike, **kwargs): + init_axi_mem(path, kwargs) + super().__init__(*args, **kwargs) diff --git a/xls/modules/zstd/cocotb/scoreboard.py b/xls/modules/zstd/cocotb/scoreboard.py new file mode 100644 index 0000000000..b9b64ca6e2 --- /dev/null +++ b/xls/modules/zstd/cocotb/scoreboard.py @@ -0,0 +1,69 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from dataclasses import dataclass +from queue import Queue + +from cocotb.clock import Clock +from cocotb.log import SimLog +from cocotb.utils import get_sim_time + +from xls.modules.zstd.cocotb.channel import XLSChannelMonitor +from xls.modules.zstd.cocotb.xlsstruct import XLSStruct + + +@dataclass +class LatencyQueueItem: + transaction: XLSStruct + timestamp: int + + +class LatencyScoreboard: + def __init__(self, dut, clock: Clock, req_monitor: XLSChannelMonitor, resp_monitor: XLSChannelMonitor): + self.dut = dut + self.log = SimLog(f"zstd.cocotb.scoreboard.{self.dut._name}") + self.clock = clock + self.req_monitor = req_monitor + self.resp_monitor = resp_monitor + self.pending_req = Queue() + self.results = [] + + self.req_monitor.add_callback(self._req_callback) + self.resp_monitor.add_callback(self._resp_callback) + + def _current_cycle(self): + return get_sim_time(units='step') / self.clock.period + + def _req_callback(self, transaction: XLSStruct): + self.pending_req.put(LatencyQueueItem(transaction, self._current_cycle())) + + def _resp_callback(self, transaction: XLSStruct): + latency_item = self.pending_req.get() + self.results.append(self._current_cycle() - latency_item.timestamp) + + def average_latency(self): + return sum(self.results)/len(self.results) + + def report_result(self): + if not self.pending_req.empty(): + self.log.warning(f"There are unfulfilled requests from channel {self.req_monitor.name}") + while not self.pending_req.empty(): + self.log.warning(f"Unfulfilled request: {self.pending_req.get()}") + if len(self.results) > 0: + self.log.info(f"Latency report - 1st latency: {self.results[0]}") + if len(self.results) > 1: + self.log.info(f"Latency report - 2nd latency: {self.results[1]}") + if len(self.results) > 2: + avg = sum(self.results[2:])/len(self.results[2:]) + self.log.info(f"Latency report - rest of the latencies (average): {avg}") diff --git a/xls/modules/zstd/cocotb/utils.py b/xls/modules/zstd/cocotb/utils.py new file mode 100644 index 0000000000..0930a92932 --- /dev/null +++ b/xls/modules/zstd/cocotb/utils.py @@ -0,0 +1,57 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +from pathlib import Path + +import cocotb +from cocotb.runner import check_results_file, get_runner +from cocotb.triggers import ClockCycles + +from xls.common import runfiles + + +def setup_com_iverilog(): + iverilog_path = Path(runfiles.get_path("iverilog", repository = "com_icarus_iverilog")) + vvp_path = Path(runfiles.get_path("vvp", repository = "com_icarus_iverilog")) + os.environ["PATH"] += os.pathsep + str(iverilog_path.parent) + os.environ["PATH"] += os.pathsep + str(vvp_path.parent) + build_dir = Path(os.environ['BUILD_WORKING_DIRECTORY'], "sim_build") + return build_dir + +def run_test(toplevel, test_module, verilog_sources): + build_dir = setup_com_iverilog() + runner = get_runner("icarus") + runner.build( + verilog_sources=verilog_sources, + hdl_toplevel=toplevel, + timescale=("1ns", "1ps"), + build_dir=build_dir, + defines={"SIMULATION": "1"}, + waves=True, + ) + + results_xml = runner.test( + hdl_toplevel=toplevel, + test_module=test_module, + waves=True, + ) + check_results_file(results_xml) + +@cocotb.coroutine +async def reset(clk, rst, cycles=1): + """Cocotb coroutine that performs the reset""" + rst.value = 1 + await ClockCycles(clk, cycles) + rst.value = 0 diff --git a/xls/modules/zstd/cocotb/xlsstruct.py b/xls/modules/zstd/cocotb/xlsstruct.py new file mode 100644 index 0000000000..a2d686a8af --- /dev/null +++ b/xls/modules/zstd/cocotb/xlsstruct.py @@ -0,0 +1,175 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import random +from dataclasses import asdict, astuple, dataclass, fields + +from cocotb.binary import BinaryValue + + +class TruncationError(Exception): + pass + +def xls_dataclass(cls): + """ + Class decorator for XLS structs. + Usage: + + @xls_dataclass + class MyStruct(XLSStruct): + ... + """ + return dataclass(cls, repr=False) + +@dataclass +class XLSStruct: + """ + Represents XLS struct on the Python side, allowing serialization/deserialization + to/from common formats and usage with XLS{Driver, Monitor}. + + The intended way to use this class is to inherit from it, specify the fields with + : [= ] syntax and decorate the inheriting class with + @XLSDataclass. Objects of this class can be instantiated and used like usual + dataclass objects, with a few extra methods and properties available. They can also + be passed as arguments to XLSChannelDriver.send and will be serialized to expected + bit vector. Class can be passed to XLSChannelMonitor ``struct`` constructor argument + to automatically deserialize all transfers to the provided struct. + + Example: + + from xlsstruct import XLSDataclass, XLSStruct + + @XLSDataclass + class MyStruct(XLSStruct): + data: 32 + ok: 1 + id: 4 = 0 + + monitor = XLSChannelMonitor(dut, CHANNEL_PREFIX, dut.clk, MyStruct) + + driver = XLSChannelDriver(dut, CHANNEL_PREFIX, dut.clk) + driver.send(MyStruct( + data = 0xdeadbeef, + ok = 1, + id = 3, + )) + # struct fields can also be randomized + driver.send(MyStruct.randomize()) + """ + + @classmethod + def _masks(cls): + """ + Returns a list of field-sized bitmasks. + + For example for fields of widths 2, 3, 4 + returns [2'b11, 3'b111, 4'b1111]. + """ + masks = [] + for field in fields(cls): + width = field.type + masks += [(1 << width) - 1] + return masks + + @classmethod + def _positions(cls): + """ + Returns a list of start positions in a bit vector for + struct's fields. + + For example for fields of widths 1, 2, 3, 4, 5, 6 + returns [20, 18, 15, 11, 6, 0] + """ + positions = [] + for i, field in enumerate(fields(cls)): + width = field.type + if i == 0: + positions += [cls.total_width - width] + else: + positions += [positions[i-1] - width] + return positions + + @classmethod + @property + def total_width(cls): + """ + Returns total bit width of the struct + """ + return sum(field.type for field in fields(cls)) + + @property + def value(self): + """ + Returns struct's value as a Python integer + """ + value = 0 + masks = self._masks() + positions = self._positions() + for field_val, mask, pos in zip(astuple(self), masks, positions): + if field_val > mask: + raise TruncationError(f"Signal value is wider than its bit width") + value |= (field_val & mask) << pos + return value + + @property + def binaryvalue(self): + """ + Returns struct's value as a cocotb.binary.BinaryValue + """ + return BinaryValue(self.binstr) + + @property + def binstr(self): + """ + Returns struct's value as a string with its binary representation + """ + return f"{self.value:>0{self.total_width}b}" + + @property + def hexstr(self): + """ + Returns struct's value as a string with its hex representation + (without leading "0x") + """ + return f"{self.value:>0{self.total_width // 4}x}" + + @classmethod + def from_int(cls, value): + """ + Returns an instance of the struct from Python integer + """ + instance = {} + masks = cls._masks() + positions = cls._positions() + for field, mask, pos in zip(fields(cls), masks, positions): + instance[field.name] = (value >> pos) & mask + return cls(**instance) + + @classmethod + def randomize(cls): + """ + Returns an instance of the struct with all fields' values randomized + """ + instance = {} + for field in fields(cls): + instance[field.name] = random.randrange(0, 2**field.type) + return cls(**instance) + + def __str__(self): + return self.__repr__() + + def __repr__(self): + classname = self.__class__.__name__ + fields = [f"{name}={hex(value)}" for name, value in asdict(self).items()] + return f"{classname}({', '.join(fields)})" diff --git a/xls/modules/zstd/memory/BUILD b/xls/modules/zstd/memory/BUILD index 2f1cadae30..dec4e61348 100644 --- a/xls/modules/zstd/memory/BUILD +++ b/xls/modules/zstd/memory/BUILD @@ -16,6 +16,7 @@ load("@rules_hdl//place_and_route:build_defs.bzl", "place_and_route") load("@rules_hdl//synthesis:build_defs.bzl", "benchmark_synth", "synthesize_rtl") load("@rules_hdl//verilog:providers.bzl", "verilog_library") +load("@xls_pip_deps//:requirements.bzl", "requirement") load( "//xls/build_rules:xls_build_defs.bzl", "xls_benchmark_ir", @@ -547,6 +548,33 @@ place_and_route( target_die_utilization_percentage = "10", ) +py_test( + name = "mem_reader_cocotb_test", + srcs = ["mem_reader_cocotb_test.py"], + data = [ + ":mem_reader_adv.v", + ":mem_reader_wrapper.v", + "@com_icarus_iverilog//:iverilog", + "@com_icarus_iverilog//:vvp", + ], + env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("cocotb"), + requirement("cocotbext-axi"), + requirement("pytest"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:channel", + "//xls/modules/zstd/cocotb:memory", + "//xls/modules/zstd/cocotb:utils", + "//xls/modules/zstd/cocotb:xlsstruct", + "@abseil-py//absl:app", + "@abseil-py//absl/flags", + "@com_google_protobuf//:protobuf_python", + ], +) + xls_dslx_library( name = "axi_writer_dslx", srcs = ["axi_writer.x"], @@ -616,6 +644,33 @@ place_and_route( target_die_utilization_percentage = "10", ) +py_test( + name = "axi_writer_cocotb_test", + srcs = ["axi_writer_cocotb_test.py"], + data = [ + ":axi_writer.v", + ":axi_writer_wrapper.v", + "@com_icarus_iverilog//:iverilog", + "@com_icarus_iverilog//:vvp", + ], + env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, + imports = ["."], + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("cocotb"), + requirement("cocotbext-axi"), + requirement("pytest"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:channel", + "//xls/modules/zstd/cocotb:utils", + "//xls/modules/zstd/cocotb:xlsstruct", + "@abseil-py//absl:app", + "@abseil-py//absl/flags", + "@com_google_protobuf//:protobuf_python", + ], +) + xls_dslx_library( name = "axi_stream_add_empty_dslx", srcs = ["axi_stream_add_empty.x"], @@ -754,3 +809,30 @@ place_and_route( tags = ["manual"], target_die_utilization_percentage = "10", ) + +py_test( + name = "mem_writer_cocotb_test", + srcs = ["mem_writer_cocotb_test.py"], + data = [ + ":mem_writer.v", + ":mem_writer_wrapper.v", + "@com_icarus_iverilog//:iverilog", + "@com_icarus_iverilog//:vvp", + ], + env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, + imports = ["."], + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("cocotb"), + requirement("cocotbext-axi"), + requirement("pytest"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:channel", + "//xls/modules/zstd/cocotb:utils", + "//xls/modules/zstd/cocotb:xlsstruct", + "@abseil-py//absl:app", + "@abseil-py//absl/flags", + "@com_google_protobuf//:protobuf_python", + ], +) diff --git a/xls/modules/zstd/memory/axi_writer_cocotb_test.py b/xls/modules/zstd/memory/axi_writer_cocotb_test.py new file mode 100644 index 0000000000..b30876a687 --- /dev/null +++ b/xls/modules/zstd/memory/axi_writer_cocotb_test.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import random +import logging +from pathlib import Path + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import ClockCycles, Event +from cocotb.binary import BinaryValue +from cocotb_bus.scoreboard import Scoreboard + +from cocotbext.axi.axis import AxiStreamSource, AxiStreamBus, AxiStreamFrame +from cocotbext.axi.axi_channels import AxiAWBus, AxiWBus, AxiBBus, AxiWriteBus, AxiAWMonitor, AxiWMonitor, AxiBMonitor, AxiBTransaction, AxiBSource, AxiBSink +from cocotbext.axi.axi_ram import AxiRamWrite +from cocotbext.axi.sparse_memory import SparseMemory + +from xls.modules.zstd.cocotb.channel import ( + XLSChannel, + XLSChannelDriver, + XLSChannelMonitor, +) +from xls.modules.zstd.cocotb.utils import reset, run_test +from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass + +ID_WIDTH = 4 +ADDR_WIDTH = 16 + +# Override default widths of AXI response signals +signal_widths = {"bresp": 3} +AxiBBus._signal_widths = signal_widths +AxiBTransaction._signal_widths = signal_widths +AxiBSource._signal_widths = signal_widths +AxiBSink._signal_widths = signal_widths +AxiBMonitor._signal_widths = signal_widths + +@xls_dataclass +class AxiWriterRespStruct(XLSStruct): + status: 1 + +@xls_dataclass +class WriteRequestStruct(XLSStruct): + address: ADDR_WIDTH + length: ADDR_WIDTH + +def set_termination_event(monitor, event, transactions): + def terminate_cb(_): + if monitor.stats.received_transactions == transactions: + event.set() + monitor.add_callback(terminate_cb) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def ram_test(dut): + GENERIC_ADDR_REQ_CHANNEL = "write_req" + GENERIC_ADDR_RESP_CHANNEL = "write_resp" + AXI_STREAM_CHANNEL = "axi_st_read" + AXI_AW_CHANNEL = "axi_aw" + AXI_W_CHANNEL = "axi_w" + AXI_B_CHANNEL = "axi_b" + + terminate = Event() + + mem_size = 2**ADDR_WIDTH + test_count = 200 + + (addr_req_input, axi_st_input, addr_resp_expect, memory_verification, expected_memory) = generate_test_data_random(test_count, mem_size) + + dut.rst.setimmediatevalue(0) + + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + resp_bus = XLSChannel(dut, GENERIC_ADDR_RESP_CHANNEL, dut.clk, start_now=True) + + driver_addr_req = XLSChannelDriver(dut, GENERIC_ADDR_REQ_CHANNEL, dut.clk) + driver_axi_st = AxiStreamSource(AxiStreamBus.from_prefix(dut, AXI_STREAM_CHANNEL), dut.clk, dut.rst) + + bus_axi_aw = AxiAWBus.from_prefix(dut, AXI_AW_CHANNEL) + bus_axi_w = AxiWBus.from_prefix(dut, AXI_W_CHANNEL) + bus_axi_b = AxiBBus.from_prefix(dut, AXI_B_CHANNEL) + bus_axi_write = AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) + + monitor_addr_req = XLSChannelMonitor(dut, GENERIC_ADDR_REQ_CHANNEL, dut.clk, WriteRequestStruct) + monitor_addr_resp = XLSChannelMonitor(dut, GENERIC_ADDR_RESP_CHANNEL, dut.clk, AxiWriterRespStruct) + monitor_axi_aw = AxiAWMonitor(bus_axi_aw, dut.clk, dut.rst) + monitor_axi_w = AxiWMonitor(bus_axi_w, dut.clk, dut.rst) + monitor_axi_b = AxiBMonitor(bus_axi_b, dut.clk, dut.rst) + + set_termination_event(monitor_addr_resp, terminate, test_count) + + memory = AxiRamWrite(bus_axi_write, dut.clk, dut.rst, size=mem_size) + + log = logging.getLogger("cocotb.tb") + log.setLevel(logging.WARNING) + memory.log.setLevel(logging.WARNING) + driver_axi_st.log.setLevel(logging.WARNING) + + scoreboard = Scoreboard(dut) + scoreboard.add_interface(monitor_addr_resp, addr_resp_expect) + + await reset(dut.clk, dut.rst, cycles=10) + await cocotb.start(driver_addr_req.send(addr_req_input)) + await cocotb.start(drive_axi_st(driver_axi_st, axi_st_input)) + await terminate.wait() + + for bundle in memory_verification: + memory_contents = bytearray(memory.read(bundle["base_address"], bundle["length"])) + expected_memory_contents = bytearray(expected_memory.read(bundle["base_address"], bundle["length"])) + assert memory_contents == expected_memory_contents, "{} bytes of memory contents at base address {}:\n{}\nvs\n{}\nHEXDUMP:\n{}\nvs\n{}".format(hex(bundle["length"]), hex(bundle["base_address"]), memory_contents, expected_memory_contents, memory.hexdump(bundle["base_address"], bundle["length"]), expected_memory.hexdump(bundle["base_address"], bundle["length"])) + +@cocotb.coroutine +async def drive_axi_st(driver, inputs): + for axi_st_input in inputs: + await driver.send(axi_st_input) + +def generate_test_data_random(test_count, mem_size): + AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x + + addr_req_input = [] + axi_st_input = [] + addr_resp_expect = [] + memory_verification = [] + memory = SparseMemory(mem_size) + + random.seed(1234) + + for i in range(test_count): + xfer_addr = random.randrange(0, mem_size) + # Don't allow unaligned writes + xfer_addr_aligned = (xfer_addr // 4) * 4 + # Make sure we don't write beyond available memory + memory_size_max_xfer_len = mem_size - xfer_addr_aligned + arbitrary_max_xfer_len = 0x5000 # 20kB + xfer_max_len = min(arbitrary_max_xfer_len, memory_size_max_xfer_len) + xfer_len = random.randrange(1, xfer_max_len) + transfer_req = WriteRequestStruct( + address = xfer_addr_aligned, + length = xfer_len, + ) + addr_req_input.append(transfer_req) + + data_to_write = random.randbytes(xfer_len) + axi_st_frame = AxiStreamFrame(tdata=data_to_write, tkeep=[15]*xfer_len, tid=(i % (1 << ID_WIDTH)), tdest=(i % (1 << ID_WIDTH))) + axi_st_input.append(axi_st_frame) + + write_expected_memory(transfer_req, axi_st_frame.tdata, memory) + + memory_bundle = { + "base_address": transfer_req.address, + "length": transfer_req.length, + } + memory_verification.append(memory_bundle) + + addr_resp_expect = [AxiWriterRespStruct(status=False)] * test_count + + return (addr_req_input, axi_st_input, addr_resp_expect, memory_verification, memory) + +def bytes_to_4k_boundary(addr): + AXI_4K_BOUNDARY = 0x1000 + return AXI_4K_BOUNDARY - (addr % AXI_4K_BOUNDARY) + +def write_expected_memory(transfer_req, data_to_write, memory): + """ + Write test data to reference memory keeping the AXI 4kb boundary + by spliting the write requests into smaller ones. + """ + prev_id = 0 + address = transfer_req.address + length = transfer_req.length + + BYTES_IN_TRANSFER = 4 + MAX_AXI_BURST_BYTES = 256 * BYTES_IN_TRANSFER + + while (length > 0): + bytes_to_4k = bytes_to_4k_boundary(address) + new_len = min(length, min(bytes_to_4k, MAX_AXI_BURST_BYTES)) + new_data = data_to_write[prev_id:prev_id+new_len] + memory.write(address, new_data) + address = address + new_len + length = length - new_len + prev_id = prev_id + new_len + +def generate_test_data_arbitrary(mem_size): + AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x + + addr_req_input = [] + axi_st_input = [] + addr_resp_expect = [] + memory_verification = [] + memory = SparseMemory(mem_size) + + xfer_addr_begin = [0, 8, 512, 1000, 0x1234, 256] + xfer_len = [1, 2, 4, 8, 0x48d, 4] + assert len(xfer_len) == len(xfer_addr_begin) + testcase_num = len(xfer_addr_begin) # test cases to execute + for i in range(testcase_num): + transfer_req = WriteRequestStruct( + address = xfer_addr_begin[i], + length = xfer_len[i] * 4, # xfer_len[i] transfers per 4 bytes + ) + addr_req_input.append(transfer_req) + + data_chunks = [] + data_bytes = [[(0xEF + j) & 0xFF, 0xBE, 0xAD, 0xDE] for j in range(xfer_len[i])] + data_words = [int.from_bytes(data_bytes[j]) for j in range(xfer_len[i])] + for j in range(xfer_len[i]): + data_chunks += data_bytes[j] + data_to_write = bytearray(data_chunks) + axi_st_frame = AxiStreamFrame(tdata=data_to_write, tkeep=[15]*xfer_len[i], tid=i, tdest=i) + axi_st_input.append(axi_st_frame) + + write_expected_memory(transfer_req, axi_st_frame.tdata, memory) + + memory_bundle = { + "base_address": transfer_req.address, + "length": transfer_req.length, # 4 byte words + } + memory_verification.append(memory_bundle) + + addr_resp_expect = [AxiWriterRespStruct(status=False)] * testcase_num + + return (addr_req_input, axi_st_input, addr_resp_expect, memory_verification, memory) + +if __name__ == "__main__": + toplevel = "axi_writer_wrapper" + verilog_sources = [ + "xls/modules/zstd/memory/axi_writer.v", + "xls/modules/zstd/memory/axi_writer_wrapper.v", + ] + test_module=[Path(__file__).stem] + run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/axi_writer_wrapper.v b/xls/modules/zstd/memory/axi_writer_wrapper.v new file mode 100644 index 0000000000..556f839284 --- /dev/null +++ b/xls/modules/zstd/memory/axi_writer_wrapper.v @@ -0,0 +1,119 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +`default_nettype none + +module axi_writer_wrapper ( + input wire clk, + input wire rst, + + output wire write_resp_data, + output wire write_resp_vld, + input wire write_resp_rdy, + + input wire [31:0] write_req_data, + input wire write_req_vld, + output wire write_req_rdy, + + input wire [31:0] axi_st_read_tdata, + input wire [3:0] axi_st_read_tstr, + input wire [3:0] axi_st_read_tkeep, + input wire [0:0] axi_st_read_tlast, + input wire [3:0] axi_st_read_tid, + input wire [3:0] axi_st_read_tdest, + input wire axi_st_read_tvalid, + output wire axi_st_read_tready, + + output wire [3:0] axi_aw_awid, + output wire [15:0] axi_aw_awaddr, + output wire [2:0] axi_aw_awsize, + output wire [7:0] axi_aw_awlen, + output wire [1:0] axi_aw_awburst, + output wire axi_aw_awvalid, + input wire axi_aw_awready, + + output wire [31:0] axi_w_wdata, + output wire [3:0] axi_w_wstrb, + output wire [0:0] axi_w_wlast, + output wire axi_w_wvalid, + input wire axi_w_wready, + + input wire [2:0] axi_b_bresp, + input wire [3:0] axi_b_bid, + input wire axi_b_bvalid, + output wire axi_b_bready + +); + + wire [32:0] axi_writer__ch_axi_aw_data; + wire [36:0] axi_writer__ch_axi_w_data; + wire [ 6:0] axi_writer__ch_axi_b_data; + + wire [15:0] write_req_data_address; + wire [15:0] write_req_data_length; + + wire [48:0] axi_st_read_data; + + assign {write_req_data_address, write_req_data_length} = write_req_data; + + assign { axi_aw_awid, + axi_aw_awaddr, + axi_aw_awsize, + axi_aw_awlen, + axi_aw_awburst } = axi_writer__ch_axi_aw_data; + + assign {axi_w_wdata, axi_w_wstrb, axi_w_wlast} = axi_writer__ch_axi_w_data; + + assign axi_writer__ch_axi_b_data = {axi_b_bresp, axi_b_bid}; + + assign axi_st_read_data = { + axi_st_read_tdata, + axi_st_read_tstr, + axi_st_read_tkeep, + axi_st_read_tlast, + axi_st_read_tid, + axi_st_read_tdest + }; + + axi_writer axi_writer ( + .clk(clk), + .rst(rst), + + .axi_writer__ch_write_req_data(write_req_data), + .axi_writer__ch_write_req_rdy (write_req_rdy), + .axi_writer__ch_write_req_vld (write_req_vld), + + .axi_writer__ch_write_resp_rdy (write_resp_rdy), + .axi_writer__ch_write_resp_vld (write_resp_vld), + .axi_writer__ch_write_resp_data(write_resp_data), + + .axi_writer__ch_axi_aw_data(axi_writer__ch_axi_aw_data), + .axi_writer__ch_axi_aw_rdy (axi_aw_awready), + .axi_writer__ch_axi_aw_vld (axi_aw_awvalid), + + .axi_writer__ch_axi_w_data(axi_writer__ch_axi_w_data), + .axi_writer__ch_axi_w_rdy (axi_w_wready), + .axi_writer__ch_axi_w_vld (axi_w_wvalid), + + .axi_writer__ch_axi_b_data(axi_writer__ch_axi_b_data), + .axi_writer__ch_axi_b_rdy (axi_b_bready), + .axi_writer__ch_axi_b_vld (axi_b_bvalid), + + .axi_writer__ch_axi_st_read_data(axi_st_read_data), + .axi_writer__ch_axi_st_read_rdy (axi_st_read_tready), + .axi_writer__ch_axi_st_read_vld (axi_st_read_tvalid) + ); + + +endmodule : axi_writer_wrapper diff --git a/xls/modules/zstd/memory/mem_reader_cocotb_test.py b/xls/modules/zstd/memory/mem_reader_cocotb_test.py new file mode 100644 index 0000000000..845a321159 --- /dev/null +++ b/xls/modules/zstd/memory/mem_reader_cocotb_test.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import random +import sys +import warnings +from pathlib import Path + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import ClockCycles, Event +from cocotb_bus.scoreboard import Scoreboard +from cocotbext.axi.axi_channels import AxiARBus, AxiRBus, AxiReadBus, AxiRTransaction, AxiRSource, AxiRSink, AxiRMonitor +from cocotbext.axi.axi_ram import AxiRamRead +from cocotbext.axi.sparse_memory import SparseMemory + +from xls.modules.zstd.cocotb.channel import ( + XLSChannel, + XLSChannelDriver, + XLSChannelMonitor, +) +from xls.modules.zstd.cocotb.utils import reset, run_test +from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass + +# to disable warnings from hexdiff used by cocotb's Scoreboard +warnings.filterwarnings("ignore", category=DeprecationWarning) + +DSLX_DATA_W = 64 +DSLX_ADDR_W = 16 + +AXI_DATA_W = 128 +AXI_ADDR_W = 16 + +LAST_W = 1 +STATUS_W = 1 +ERROR_W = 1 +ID_W = 4 +DEST_W = 4 + +# AXI +AXI_AR_PREFIX = "axi_ar" +AXI_R_PREFIX = "axi_r" + +# MemReader +MEM_READER_REQ_CHANNEL = "req" +MEM_READER_RESP_CHANNEL = "resp" + +# Override default widths of AXI response signals +signal_widths = {"rresp": 3, "rlast": 1} +AxiRBus._signal_widths = signal_widths +AxiRTransaction._signal_widths = signal_widths +AxiRSource._signal_widths = signal_widths +AxiRSink._signal_widths = signal_widths +AxiRMonitor._signal_widths = signal_widths + +@xls_dataclass +class MemReaderReq(XLSStruct): + addr: DSLX_ADDR_W + length: DSLX_ADDR_W + + +@xls_dataclass +class MemReaderResp(XLSStruct): + status: STATUS_W + data: DSLX_DATA_W + length: DSLX_ADDR_W + last: LAST_W + + +@xls_dataclass +class AxiReaderReq(XLSStruct): + addr: AXI_ADDR_W + len: AXI_ADDR_W + + +@xls_dataclass +class AxiStream(XLSStruct): + data: AXI_DATA_W + str: AXI_DATA_W // 8 + keep: AXI_DATA_W // 8 = 0 + last: LAST_W = 0 + id: ID_W = 0 + dest: DEST_W = 0 + + +@xls_dataclass +class AxiReaderError(XLSStruct): + error: ERROR_W + + +@xls_dataclass +class AxiAr(XLSStruct): + id: ID_W + addr: AXI_ADDR_W + region: 4 + len: 8 + size: 3 + burst: 2 + cache: 4 + prot: 3 + qos: 4 + + +@xls_dataclass +class AxiR(XLSStruct): + id: ID_W + data: AXI_DATA_W + resp: 3 + last: 1 + + +def print_callback(name: str = "monitor"): + def _print_callback(transaction): + print(f" [{name}]: {transaction}") + + return _print_callback + + +def set_termination_event(monitor, event, transactions): + def terminate_cb(_): + if monitor.stats.received_transactions == transactions: + print("all transactions received") + event.set() + + monitor.add_callback(terminate_cb) + + +def generate_test_data(test_cases, xfer_base=0x0, seed=1234): + random.seed(seed) + mem_size = 2**AXI_ADDR_W + data_w_div8 = DSLX_DATA_W // 8 + + assert xfer_base < mem_size, "Base address outside the memory span" + + req = [] + resp = [] + mem_writes = {} + + for xfer_offset, xfer_length in test_cases: + xfer_addr = xfer_base + xfer_offset + xfer_max_addr = xfer_addr + xfer_length + + if xfer_length == 0: + req += [MemReaderReq(addr=xfer_addr, length=0)] + resp += [MemReaderResp(status=0, data=0, length=0, last=1)] + + assert xfer_max_addr < mem_size, "Max address outside the memory span" + req += [MemReaderReq(addr=xfer_addr, length=xfer_length)] + + rem = xfer_length % data_w_div8 + for addr in range(xfer_addr, xfer_max_addr - (data_w_div8 - 1), data_w_div8): + last = ((addr + data_w_div8) >= xfer_max_addr) & (rem == 0) + data = random.randint(0, 1 << (data_w_div8 * 8)) + mem_writes.update({addr: data}) + resp += [MemReaderResp(status=0, data=data, length=data_w_div8, last=last)] + + if rem > 0: + addr = xfer_max_addr - rem + mask = (1 << (rem * 8)) - 1 + data = random.randint(0, 1 << (data_w_div8 * 8)) + mem_writes.update({addr: data}) + resp += [MemReaderResp(status=0, data=data & mask, length=rem, last=1)] + + return (req, resp, mem_writes) + + +async def test_mem_reader(dut, req_input, resp_output, mem_contents={}): + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + mem_reader_resp_bus = XLSChannel( + dut, MEM_READER_RESP_CHANNEL, dut.clk, start_now=True + ) + mem_reader_req_driver = XLSChannelDriver(dut, MEM_READER_REQ_CHANNEL, dut.clk) + mem_reader_resp_monitor = XLSChannelMonitor( + dut, MEM_READER_RESP_CHANNEL, dut.clk, MemReaderResp, callback=print_callback() + ) + + terminate = Event() + set_termination_event(mem_reader_resp_monitor, terminate, len(resp_output)) + + scoreboard = Scoreboard(dut) + scoreboard.add_interface(mem_reader_resp_monitor, resp_output) + + ar_bus = AxiARBus.from_prefix(dut, AXI_AR_PREFIX) + r_bus = AxiRBus.from_prefix(dut, AXI_R_PREFIX) + axi_read_bus = AxiReadBus(ar=ar_bus, r=r_bus) + + mem_size = 2**AXI_ADDR_W + sparse_mem = SparseMemory(mem_size) + for addr, data in mem_contents.items(): + sparse_mem.write(addr, (data).to_bytes(8, "little")) + + memory = AxiRamRead(axi_read_bus, dut.clk, dut.rst, size=mem_size, mem=sparse_mem) + + await reset(dut.clk, dut.rst, cycles=10) + await mem_reader_req_driver.send(req_input) + await terminate.wait() + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def mem_reader_zero_length_req(dut): + req, resp, _ = generate_test_data( + xfer_base=0xFFF, test_cases=[(0x101, 0)] + ) + await test_mem_reader(dut, req, resp) + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def mem_reader_aligned_transfer_shorter_than_bus(dut): + req, resp, mem_contents = generate_test_data( + xfer_base=0xFFF, test_cases=[(0x101, 1)] + ) + await test_mem_reader(dut, req, resp, mem_contents) + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def mem_reader_aligned_transfer_shorter_than_bus1(dut): + req, resp, mem_contents = generate_test_data( + xfer_base=0xFFF, test_cases=[(0x2, 1)] + ) + await test_mem_reader(dut, req, resp, mem_contents) + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def mem_reader_aligned_transfer_shorter_than_bus2(dut): + req, resp, mem_contents = generate_test_data( + xfer_base=0xFFF, test_cases=[(0x2, 17)] + ) + await test_mem_reader(dut, req, resp, mem_contents) + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def mem_reader_aligned_transfer_shorter_than_bus3(dut): + req, resp, mem_contents = generate_test_data( + xfer_base=0xFFF, test_cases=[(0x0, 0x1000)] + ) + await test_mem_reader(dut, req, resp, mem_contents) + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def mem_reader_aligned_transfer_shorter_than_bus4(dut): + req, resp, mem_contents = generate_test_data( + xfer_base=0x1, test_cases=[(0x0, 0xFFF), (0x1000, 0x1)] + ) + await test_mem_reader(dut, req, resp, mem_contents) + + +if __name__ == "__main__": + sys.path.append(str(Path(__file__).parent)) + + toplevel = "mem_reader_wrapper" + verilog_sources = [ + "xls/modules/zstd/memory/mem_reader_adv.v", + "xls/modules/zstd/memory/mem_reader_wrapper.v", + ] + test_module = [Path(__file__).stem] + run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/mem_reader_wrapper.v b/xls/modules/zstd/memory/mem_reader_wrapper.v new file mode 100644 index 0000000000..3601bcbb0e --- /dev/null +++ b/xls/modules/zstd/memory/mem_reader_wrapper.v @@ -0,0 +1,111 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +`default_nettype none + +module mem_reader_wrapper #( + parameter DSLX_DATA_W = 64, + parameter DSLX_ADDR_W = 16, + parameter AXI_DATA_W = 128, + parameter AXI_ADDR_W = 16, + parameter AXI_DEST_W = 8, + parameter AXI_ID_W = 8, + + parameter CTRL_W = (DSLX_ADDR_W), + parameter REQ_W = (2 * DSLX_ADDR_W), + parameter RESP_W = (1 + DSLX_DATA_W + DSLX_ADDR_W + 1), + parameter AXI_AR_W = (AXI_ID_W + AXI_ADDR_W + 28), + parameter AXI_R_W = (AXI_ID_W + AXI_DATA_W + 4) +) ( + input wire clk, + input wire rst, + + output wire req_rdy, + input wire req_vld, + input wire [REQ_W-1:0] req_data, + + output wire resp_vld, + input wire resp_rdy, + output wire [RESP_W-1:0] resp_data, + + output wire axi_ar_arvalid, + input wire axi_ar_arready, + output wire [ AXI_ID_W-1:0] axi_ar_arid, + output wire [AXI_ADDR_W-1:0] axi_ar_araddr, + output wire [ 3:0] axi_ar_arregion, + output wire [ 7:0] axi_ar_arlen, + output wire [ 2:0] axi_ar_arsize, + output wire [ 1:0] axi_ar_arburst, + output wire [ 3:0] axi_ar_arcache, + output wire [ 2:0] axi_ar_arprot, + output wire [ 3:0] axi_ar_arqos, + + input wire axi_r_rvalid, + output wire axi_r_rready, + input wire [ AXI_ID_W-1:0] axi_r_rid, + input wire [AXI_DATA_W-1:0] axi_r_rdata, + input wire [ 2:0] axi_r_rresp, + input wire axi_r_rlast +); + + wire [AXI_AR_W-1:0] axi_ar_data; + wire axi_ar_rdy; + wire axi_ar_vld; + + assign axi_ar_rdy = axi_ar_arready; + + assign axi_ar_arvalid = axi_ar_vld; + assign { + axi_ar_arid, + axi_ar_araddr, + axi_ar_arregion, + axi_ar_arlen, + axi_ar_arsize, + axi_ar_arburst, + axi_ar_arcache, + axi_ar_arprot, + axi_ar_arqos +} = axi_ar_data; + + wire [AXI_R_W-1:0] axi_r_data; + wire axi_r_vld; + wire axi_r_rdy; + + assign axi_r_data = {axi_r_rid, axi_r_rdata, axi_r_rresp, axi_r_rlast}; + assign axi_r_vld = axi_r_rvalid; + + assign axi_r_rready = axi_r_rdy; + + mem_reader_adv mem_reader_adv ( + .clk(clk), + .rst(rst), + + .mem_reader__req_r_data(req_data), + .mem_reader__req_r_rdy (req_rdy), + .mem_reader__req_r_vld (req_vld), + + .mem_reader__resp_s_data(resp_data), + .mem_reader__resp_s_rdy (resp_rdy), + .mem_reader__resp_s_vld (resp_vld), + + .mem_reader__axi_ar_s_data(axi_ar_data), + .mem_reader__axi_ar_s_rdy (axi_ar_rdy), + .mem_reader__axi_ar_s_vld (axi_ar_vld), + + .mem_reader__axi_r_r_data(axi_r_data), + .mem_reader__axi_r_r_vld (axi_r_vld), + .mem_reader__axi_r_r_rdy (axi_r_rdy) + ); + +endmodule diff --git a/xls/modules/zstd/memory/mem_writer_cocotb_test.py b/xls/modules/zstd/memory/mem_writer_cocotb_test.py new file mode 100644 index 0000000000..63d6e29cbf --- /dev/null +++ b/xls/modules/zstd/memory/mem_writer_cocotb_test.py @@ -0,0 +1,667 @@ +#!/usr/bin/env python +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import random +import logging +from enum import Enum +from pathlib import Path + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import ClockCycles, Event +from cocotb.binary import BinaryValue +from cocotb_bus.scoreboard import Scoreboard + +from cocotbext.axi.axis import AxiStreamSource, AxiStreamBus, AxiStreamFrame +from cocotbext.axi.axi_channels import AxiAWBus, AxiWBus, AxiBBus, AxiWriteBus, AxiAWMonitor, AxiWMonitor, AxiBMonitor, AxiBTransaction, AxiBSource, AxiBSink +from cocotbext.axi.axi_ram import AxiRamWrite +from cocotbext.axi.sparse_memory import SparseMemory + +from xls.modules.zstd.cocotb.channel import ( + XLSChannel, + XLSChannelDriver, + XLSChannelMonitor, +) +from xls.modules.zstd.cocotb.utils import reset, run_test +from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass + +DATA_WIDTH = 32 +ADDR_WIDTH = 16 + +# Override default widths of AXI response signals +signal_widths = {"bresp": 3} +AxiBBus._signal_widths = signal_widths +AxiBTransaction._signal_widths = signal_widths +AxiBSource._signal_widths = signal_widths +AxiBSink._signal_widths = signal_widths +AxiBMonitor._signal_widths = signal_widths + +@xls_dataclass +class DataInStruct(XLSStruct): + data: DATA_WIDTH + length: ADDR_WIDTH + last: 1 + +@xls_dataclass +class WriteReqStruct(XLSStruct): + offset: ADDR_WIDTH + length: ADDR_WIDTH + +@xls_dataclass +class MemWriterRespStruct(XLSStruct): + status: 1 + +class MemWriterRespStatus(Enum): + OKAY = 0 + ERROR = 1 + +@xls_dataclass +class WriteRequestStruct(XLSStruct): + address: ADDR_WIDTH + length: ADDR_WIDTH + +def set_termination_event(monitor, event, transactions): + def terminate_cb(_): + if monitor.stats.received_transactions == transactions: + event.set() + monitor.add_callback(terminate_cb) + +async def test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt): + GENERIC_WRITE_REQ_CHANNEL = "req" + GENERIC_WRITE_RESP_CHANNEL = "resp" + GENERIC_DATA_IN_CHANNEL = "data_in" + AXI_AW_CHANNEL = "axi_aw" + AXI_W_CHANNEL = "axi_w" + AXI_B_CHANNEL = "axi_b" + + terminate = Event() + + dut.rst.setimmediatevalue(0) + + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + resp_bus = XLSChannel(dut, GENERIC_WRITE_RESP_CHANNEL, dut.clk, start_now=True) + + driver_write_req = XLSChannelDriver(dut, GENERIC_WRITE_REQ_CHANNEL, dut.clk) + driver_data_in = XLSChannelDriver(dut, GENERIC_DATA_IN_CHANNEL, dut.clk) + + bus_axi_aw = AxiAWBus.from_prefix(dut, AXI_AW_CHANNEL) + bus_axi_w = AxiWBus.from_prefix(dut, AXI_W_CHANNEL) + bus_axi_b = AxiBBus.from_prefix(dut, AXI_B_CHANNEL) + bus_axi_write = AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) + + monitor_write_req = XLSChannelMonitor(dut, GENERIC_WRITE_REQ_CHANNEL, dut.clk, WriteRequestStruct) + monitor_data_in = XLSChannelMonitor(dut, GENERIC_DATA_IN_CHANNEL, dut.clk, WriteRequestStruct) + monitor_write_resp = XLSChannelMonitor(dut, GENERIC_WRITE_RESP_CHANNEL, dut.clk, MemWriterRespStruct) + monitor_axi_aw = AxiAWMonitor(bus_axi_aw, dut.clk, dut.rst) + monitor_axi_w = AxiWMonitor(bus_axi_w, dut.clk, dut.rst) + monitor_axi_b = AxiBMonitor(bus_axi_b, dut.clk, dut.rst) + + set_termination_event(monitor_write_resp, terminate, resp_cnt) + + memory = AxiRamWrite(bus_axi_write, dut.clk, dut.rst, size=mem_size) + + log = logging.getLogger("cocotb.tb") + log.setLevel(logging.WARNING) + memory.log.setLevel(logging.WARNING) + + scoreboard = Scoreboard(dut) + scoreboard.add_interface(monitor_write_resp, write_resp_expect) + + await reset(dut.clk, dut.rst, cycles=10) + await cocotb.start(driver_write_req.send(write_req_input)) + await cocotb.start(driver_data_in.send(data_in_input)) + + await terminate.wait() + + for bundle in memory_verification: + memory_contents = bytearray(memory.read(bundle["base_address"], bundle["length"])) + expected_memory_contents = bytearray(expected_memory.read(bundle["base_address"], bundle["length"])) + assert memory_contents == expected_memory_contents, "{} bytes of memory contents at base address {}:\n{}\nvs\n{}\nHEXDUMP:\n{}\nvs\n{}".format(hex(bundle["length"]), hex(bundle["base_address"]), memory_contents, expected_memory_contents, memory.hexdump(bundle["base_address"], bundle["length"]), expected_memory.hexdump(bundle["base_address"], bundle["length"])) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_single_burst_1_transfer(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_1_transfer) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_single_burst_2_transfers(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_2_transfers) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_single_burst_almost_max_burst_transfer(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_almost_max_burst_transfer) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_single_burst_max_burst_transfer(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_max_burst_transfer) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_multiburst_2_full_bursts(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_2_full_bursts) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_multiburst_1_full_burst_and_single_transfer(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_1_full_burst_and_single_transfer) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_multiburst_crossing_4kb_boundary(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_crossing_4kb_boundary) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=2000, timeout_unit="ms") +async def ram_test_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=5000, timeout_unit="ms") +async def ram_test_not_full_packets(dut): + mem_size = 2**ADDR_WIDTH + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_padded_test_data_arbitrary(mem_size, test_cases_not_full_packets) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +@cocotb.test(timeout_time=5000, timeout_unit="ms") +async def ram_test_random(dut): + mem_size = 2**ADDR_WIDTH + test_count = 200 + + (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_random(test_count, mem_size) + await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + +def generate_test_data_random(test_count, mem_size): + AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x + + write_req_input = [] + data_in_input = [] + write_resp_expect = [] + memory_verification = [] + memory = SparseMemory(mem_size) + + random.seed(1234) + + xfer_baseaddr = 0 + + for i in range(test_count): + # Generate offset from the absolute address + max_xfer_offset = mem_size - xfer_baseaddr + xfer_offset = random.randrange(0, max_xfer_offset) + xfer_addr = xfer_baseaddr + xfer_offset + # Make sure we don't write beyond available memory + memory_size_max_xfer_len = mem_size - xfer_addr + arbitrary_max_xfer_len = 0x5000 # 20kB + xfer_max_len = min(arbitrary_max_xfer_len, memory_size_max_xfer_len) + xfer_len = random.randrange(1, xfer_max_len) + + write_req = WriteReqStruct( + offset = xfer_offset, + length = xfer_len, + ) + write_req_input.append(write_req) + + data_to_write = random.randbytes(xfer_len) + rem = xfer_len % 4 + for j in list(range(0, xfer_len-3, 4)): + last = ((j + 4) >= xfer_len) & (rem == 0) + data_in = DataInStruct( + data = int.from_bytes(data_to_write[j:j+4], byteorder='little'), + length = 4, + last = last + ) + data_in_input.append(data_in) + if (rem > 0): + data_in = DataInStruct( + data = int.from_bytes(data_to_write[-rem:], byteorder='little'), + length = rem, + last = True + ) + data_in_input.append(data_in) + + + transfer_req = WriteRequestStruct( + address = xfer_addr, + length = xfer_len, + ) + write_expected_memory(transfer_req, data_to_write, memory) + + memory_bundle = { + "base_address": transfer_req.address, + "length": transfer_req.length, + } + memory_verification.append(memory_bundle) + + write_resp_expect = [MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value)] * test_count + + return (write_req_input, data_in_input, write_resp_expect, memory_verification, memory, test_count) + +def bytes_to_4k_boundary(addr): + AXI_4K_BOUNDARY = 0x1000 + return AXI_4K_BOUNDARY - (addr % AXI_4K_BOUNDARY) + +def write_expected_memory(transfer_req, data_to_write, memory): + """ + Write test data to reference memory keeping the AXI 4kb boundary + by spliting the write requests into smaller ones. + """ + prev_id = 0 + address = transfer_req.address + length = transfer_req.length + + BYTES_IN_TRANSFER = 4 + MAX_AXI_BURST_BYTES = 256 * BYTES_IN_TRANSFER + + while (length > 0): + bytes_to_4k = bytes_to_4k_boundary(address) + new_len = min(length, min(bytes_to_4k, MAX_AXI_BURST_BYTES)) + new_data = data_to_write[prev_id:prev_id+new_len] + memory.write(address, new_data) + address = address + new_len + length = length - new_len + prev_id = prev_id + new_len + +def generate_test_data_arbitrary(mem_size, test_cases): + AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x + test_count = len(test_cases) + + random.seed(1234) + + write_req_input = [] + data_in_input = [] + write_resp_expect = [] + memory_verification = [] + memory = SparseMemory(mem_size) + + xfer_baseaddr = 0x0 + assert xfer_baseaddr < mem_size + + max_xfer_offset = mem_size - xfer_baseaddr + + for xfer_offset, xfer_len in test_cases: + assert xfer_offset <= max_xfer_offset + xfer_addr = xfer_baseaddr + xfer_offset + # Make sure we don't write beyond available memory + memory_size_max_xfer_len = mem_size - xfer_addr + arbitrary_max_xfer_len = 0x5000 # 20kB + xfer_max_len = min(arbitrary_max_xfer_len, memory_size_max_xfer_len) + assert xfer_len <= xfer_max_len + + write_req = WriteReqStruct( + offset = xfer_offset, + length = xfer_len, + ) + write_req_input.append(write_req) + + data_to_write = random.randbytes(xfer_len) + rem = xfer_len % 4 + for j in list(range(0, xfer_len-3, 4)): + last = ((j + 4) >= xfer_len) & (rem == 0) + data_in = DataInStruct( + data = int.from_bytes(data_to_write[j:j+4], byteorder='little'), + length = 4, + last = last + ) + data_in_input.append(data_in) + if (rem > 0): + data_in = DataInStruct( + data = int.from_bytes(data_to_write[-rem:], byteorder='little'), + length = rem, + last = True + ) + data_in_input.append(data_in) + + + transfer_req = WriteRequestStruct( + address = xfer_addr, + length = xfer_len, + ) + write_expected_memory(transfer_req, data_to_write, memory) + + memory_bundle = { + "base_address": transfer_req.address, + "length": transfer_req.length, + } + memory_verification.append(memory_bundle) + + write_resp_expect = [MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value)] * test_count + + return (write_req_input, data_in_input, write_resp_expect, memory_verification, memory, test_count) + +def generate_padded_test_data_arbitrary(mem_size, test_cases): + AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x + test_count = len(test_cases) + + random.seed(1234) + + write_req_input = [] + data_in_input = [] + write_resp_expect = [] + memory_verification = [] + memory = SparseMemory(mem_size) + + xfer_baseaddr = 0x0 + assert xfer_baseaddr < mem_size + + max_xfer_offset = mem_size - xfer_baseaddr + + for xfer_offset, xfer_len in test_cases: + assert xfer_offset <= max_xfer_offset + xfer_addr = xfer_baseaddr + xfer_offset + # Make sure we don't write beyond available memory + memory_size_max_xfer_len = mem_size - xfer_addr + arbitrary_max_xfer_len = 0x5000 # 20kB + xfer_max_len = min(arbitrary_max_xfer_len, memory_size_max_xfer_len) + assert xfer_len <= xfer_max_len + + write_req = WriteReqStruct( + offset = xfer_offset, + length = xfer_len, + ) + write_req_input.append(write_req) + + data_to_write = random.randbytes(xfer_len) + bytes_to_packetize = xfer_len + packetized_bytes = 0 + while(bytes_to_packetize): + packet_len = random.randint(1, 4) + + if (bytes_to_packetize < packet_len): + packet_len = bytes_to_packetize + + last = packet_len == bytes_to_packetize + + data_in = DataInStruct( + data = int.from_bytes(data_to_write[packetized_bytes:packetized_bytes+packet_len], byteorder='little'), + length = packet_len, + last = last + ) + data_in_input.append(data_in) + + bytes_to_packetize -= packet_len + packetized_bytes += packet_len + assert xfer_len == packetized_bytes + + + transfer_req = WriteRequestStruct( + address = xfer_addr, + length = xfer_len, + ) + write_expected_memory(transfer_req, data_to_write, memory) + + memory_bundle = { + "base_address": transfer_req.address, + "length": transfer_req.length, + } + memory_verification.append(memory_bundle) + + write_resp_expect = [MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value)] * test_count + + return (write_req_input, data_in_input, write_resp_expect, memory_verification, memory, test_count) + +if __name__ == "__main__": + toplevel = "mem_writer_wrapper" + verilog_sources = [ + "xls/modules/zstd/memory/mem_writer.v", + "xls/modules/zstd/memory/mem_writer_wrapper.v", + ] + test_module=[Path(__file__).stem] + run_test(toplevel, test_module, verilog_sources) + +test_cases_single_burst_1_transfer = [ + # Aligned Address; Aligned Length + (0x0, 0x4), + # Aligned Address; Unaligned Length + (0x10, 0x1), + (0x24, 0x2), + (0x38, 0x3), + # Unaligned Address; Aligned Length + (0x41, 0x4), + (0x52, 0x4), + (0x63, 0x4), + # Unaligned Address; Unaligned Length + (0x71, 0x1), + (0x81, 0x2), + (0x91, 0x3), + (0xa2, 0x1), + (0xb2, 0x2), + (0xc2, 0x3), + (0xd3, 0x1), + (0xe3, 0x2), + (0xf3, 0x3) +] + +test_cases_single_burst_2_transfers = [ + # Aligned Address; Aligned Length + (0x100, 0x8), + # Aligned Address; Unaligned Length + (0x110, 0x5), + (0x120, 0x6), + (0x130, 0x7), + # Unaligned Address; Aligned Length + (0x141, 0x8), + (0x152, 0x8), + (0x163, 0x8), + # Unaligned Address; Unaligned Length + (0x171, 0x5), + (0x182, 0x5), + (0x193, 0x5), + (0x1A1, 0x6), + (0x1B2, 0x6), + (0x1C3, 0x6), + (0x1D1, 0x7), + (0x1E2, 0x7), + (0x1F3, 0x7) +] + +test_cases_single_burst_almost_max_burst_transfer = [ + # Aligned Address; Aligned Length + (0x200, 0x3FC), + # Aligned Address; Unaligned Length + (0x600, 0x3F9), + (0xA00, 0x3FA), + (0x1000, 0x3FB), + # Unaligned Address; Aligned Length + (0x1401, 0x3FC), + (0x1802, 0x3FC), + (0x2003, 0x3FC), + # Unaligned Address; Unaligned Length + (0x2401, 0x3F9), + (0x2802, 0x3F9), + (0x2C03, 0x3F9), + (0x3001, 0x3FA), + (0x3402, 0x3FA), + (0x3803, 0x3FA), + (0x3C01, 0x3FB), + (0x4002, 0x3FB), + (0x4403, 0x3FB) +] + +test_cases_single_burst_max_burst_transfer = [ + # Aligned Address; Aligned Length + (0x4800, 0x400), + # Aligned Address; Unaligned Length + (0x4C00, 0x3FD), + (0x5000, 0x3FE), + (0x5400, 0x3FF), + # Unaligned Address; Aligned Length + (0x5801, 0x400), + (0x6002, 0x400), + (0x6803, 0x400), + # Unaligned Address; Unaligned Length + (0x7001, 0x3FD), + (0x7802, 0x3FD), + (0x8003, 0x3FD), + (0x8801, 0x3FE), + (0x9002, 0x3FE), + (0x9803, 0x3FE), + (0xA001, 0x3FF), + (0xA802, 0x3FF), + (0xB003, 0x3FF) +] + +test_cases_multiburst_2_full_bursts = [ + # Aligned Address; Aligned Length + (0x0400, 0x800), + # Aligned Address; Unaligned Length + (0x1000, 0x7FD), + (0x1800, 0x7FE), + (0x2000, 0x7FF), + # Unaligned Address; Aligned Length + (0x2801, 0x800), + (0x3002, 0x800), + (0x3803, 0x800), + # Unaligned Address; Unaligned Length + (0x4001, 0x7FD), + (0x5002, 0x7FD), + (0x6003, 0x7FD), + (0x7001, 0x7FE), + (0x8002, 0x7FE), + (0x9003, 0x7FE), + (0xA001, 0x7FF), + (0xB002, 0x7FF), + (0xF003, 0x7FF) +] + +test_cases_multiburst_1_full_burst_and_single_transfer = [ + # Aligned Address; Aligned Length; Multi-Burst + (0x0000, 0x404), + # Aligned Address; Unaligned Length; Multi-Burst + (0x0800, 0x401), + (0x1000, 0x402), + (0x1800, 0x403), + # Unaligned Address; Aligned Length; Multi-Burst + (0x2000, 0x404), + (0x2800, 0x404), + (0x3000, 0x404), + # Unaligned Address; Unaligned Length; Multi-Burst + (0x3801, 0x401), + (0x5002, 0x401), + (0x5803, 0x401), + (0x6001, 0x402), + (0x6802, 0x402), + (0x7003, 0x402), + (0x7801, 0x403), + (0x8002, 0x403), + (0x8803, 0x403) +] + +test_cases_multiburst_crossing_4kb_boundary = [ + # Aligned Address; Aligned Length + (0x0FFC, 0x8), + # Aligned Address; Unaligned Length + (0x1FFC, 0x5), + (0x2FFC, 0x6), + (0x3FFC, 0x7), + # Unaligned Address; Aligned Length + (0x4FFD, 0x8), + (0x5FFE, 0x8), + (0x6FFF, 0x8), + # Unaligned Address; Unaligned Length + (0x7FFD, 0x5), + (0x8FFD, 0x6), + (0x9FFD, 0x7), + (0xAFFE, 0x5), + (0xBFFE, 0x6), + (0xCFFE, 0x7), + (0xDFFF, 0x5), + (0xEFFF, 0x6), + # End of address space - wrap around + (0x0FFF, 0x7), +] + +test_cases_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts = [ + # Aligned Address; Aligned Length; Multi-Burst; crossing 4kB boundary with perfectly aligned full bursts + (0x0C00, 0x800), + # Unaligned Address; Unaligned Length; Multi-Burst; crossing 4kB boundary with perfectly aligned full bursts + (0x1C01, 0x7FF), + (0x2C02, 0x7FE), + (0x3C03, 0x7FD), +] + +test_cases_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer = [ + # Aligned Address; Aligned Length + (0x0C04, 0x800), + # Aligned Address; Unaligned Length + (0x1C04, 0x801), + (0x2C04, 0x802), + (0x3C04, 0x803), + # Unaligned Address; Aligned Length + (0x4C01, 0x800), + (0x5C02, 0x800), + (0x6C03, 0x800), + # Unaligned Address; Unaligned Length + (0x7C01, 0x801), + (0x8C02, 0x802), + (0x9C03, 0x803), + (0xAC01, 0x802), + (0xBC02, 0x802), + (0xCC03, 0x802), + (0xDC01, 0x803), + (0xEC02, 0x803), + # End of address space - wrap around + (0x0C03, 0x803), +] + +test_cases_not_full_packets = [ + # Aligned Address; Aligned Length + (0x0000, 0x20), + # Aligned Address; Unaligned Length + (0x100, 0x21), + (0x200, 0x22), + (0x300, 0x23), + # Unaligned Address; Aligned Length + (0x401, 0x20), + (0x502, 0x20), + (0x603, 0x20), + # Unaligned Address; Unaligned Length + (0x701, 0x21), + (0x802, 0x22), + (0x903, 0x23), + (0xA01, 0x22), + (0xB02, 0x22), + (0xC03, 0x22), + (0xD01, 0x23), + (0xE02, 0x23), + (0xF03, 0x23), +] diff --git a/xls/modules/zstd/memory/mem_writer_wrapper.v b/xls/modules/zstd/memory/mem_writer_wrapper.v new file mode 100644 index 0000000000..c7513af58a --- /dev/null +++ b/xls/modules/zstd/memory/mem_writer_wrapper.v @@ -0,0 +1,193 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +`default_nettype none + +module mem_writer_wrapper ( + input wire clk, + input wire rst, + + input wire [31:0] req_data, + input wire req_vld, + output wire req_rdy, + + input wire [48:0] data_in_data, + input wire data_in_vld, + output wire data_in_rdy, + + output wire resp_data, + output wire resp_vld, + input wire resp_rdy, + + output wire [3:0] axi_aw_awid, + output wire [15:0] axi_aw_awaddr, + output wire [2:0] axi_aw_awsize, + output wire [7:0] axi_aw_awlen, + output wire [1:0] axi_aw_awburst, + output wire axi_aw_awvalid, + input wire axi_aw_awready, + + output wire [31:0] axi_w_wdata, + output wire [3:0] axi_w_wstrb, + output wire [0:0] axi_w_wlast, + output wire axi_w_wvalid, + input wire axi_w_wready, + + input wire [2:0] axi_b_bresp, + input wire [3:0] axi_b_bid, + input wire axi_b_bvalid, + output wire axi_b_bready +); + + wire [15:0] req_f_addr; + wire [15:0] req_f_length; + + wire [31:0] data_in_f_data; + wire [15:0] data_in_f_length; + wire [0:0] data_in_f_last; + + wire [36:0] axi_w_data; + wire axi_w_vld; + wire axi_w_rdy; + + wire [32:0] axi_aw_data; + wire axi_aw_vld; + wire axi_aw_rdy; + + wire [6:0] axi_b_data; + wire axi_b_rdy; + wire axi_b_vld; + + assign {req_f_addr, req_f_length} = req_data; + + assign {data_in_f_data, data_in_f_length, data_in_f_last} = data_in_data; + + assign {axi_aw_awid, axi_aw_awaddr, axi_aw_awsize, axi_aw_awlen, axi_aw_awburst} = axi_aw_data; + assign axi_aw_awvalid = axi_aw_vld; + assign axi_aw_rdy = axi_aw_awready; + + assign {axi_w_wdata, axi_w_wstrb, axi_w_wlast} = axi_w_data; + assign axi_w_wvalid = axi_w_vld; + assign axi_w_rdy = axi_w_wready; + + assign axi_b_data = {axi_b_bresp, axi_b_bid}; + assign axi_b_vld = axi_b_bvalid; + assign axi_b_bready = axi_b_rdy; + + wire [15:0] axi_writer_write_req_address; + wire [15:0] axi_writer_write_req_length; + wire [ 0:0] axi_writer_write_req_valid; + wire [ 0:0] axi_writer_write_req_ready; + + wire [15:0] padding_write_req_address; + wire [15:0] padding_write_req_length; + wire [ 0:0] padding_write_req_valid; + wire [ 0:0] padding_write_req_ready; + + wire [31:0] axi_stream_raw_tdata; + wire [ 3:0] axi_stream_raw_tstr; + wire [ 3:0] axi_stream_raw_tkeep; + wire [ 0:0] axi_stream_raw_tlast; + wire [ 3:0] axi_stream_raw_tid; + wire [ 3:0] axi_stream_raw_tdest; + wire [ 0:0] axi_stream_raw_tvalid; + wire [ 0:0] axi_stream_raw_tready; + + wire [31:0] axi_stream_clean_tdata; + wire [ 3:0] axi_stream_clean_tstr; + wire [ 3:0] axi_stream_clean_tkeep; + wire [ 0:0] axi_stream_clean_tlast; + wire [ 3:0] axi_stream_clean_tid; + wire [ 3:0] axi_stream_clean_tdest; + wire [ 0:0] axi_stream_clean_tvalid; + wire [ 0:0] axi_stream_clean_tready; + + wire [31:0] axi_stream_padded_tdata; + wire [ 3:0] axi_stream_padded_tstr; + wire [ 3:0] axi_stream_padded_tkeep; + wire [ 0:0] axi_stream_padded_tlast; + wire [ 3:0] axi_stream_padded_tid; + wire [ 3:0] axi_stream_padded_tdest; + wire [ 0:0] axi_stream_padded_tvalid; + wire [ 0:0] axi_stream_padded_tready; + + assign {axi_writer_write_req_address, axi_writer_write_req_length} = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_writer_req_data; + assign axi_writer_write_req_valid = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_writer_req_vld; + assign axi_writer_write_req_ready = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_writer_req_rdy; + + assign {padding_write_req_address, padding_write_req_length} = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__padding_req_data; + assign padding_write_req_valid = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__padding_req_vld; + assign padding_write_req_ready = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__padding_req_rdy; + + assign { axi_stream_raw_tdata, + axi_stream_raw_tstr, + axi_stream_raw_tkeep, + axi_stream_raw_tid, + axi_stream_raw_tdest, + axi_stream_raw_tlast} = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_st_raw_data; + assign axi_stream_raw_tvalid = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_st_raw_vld; + assign axi_stream_raw_tready = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_st_raw_rdy; + + assign { axi_stream_clean_tdata, + axi_stream_clean_tstr, + axi_stream_clean_tkeep, + axi_stream_clean_tid, + axi_stream_clean_tdest, + axi_stream_clean_tlast} = mem_writer.__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1.mem_writer__axi_st_clean_data; + assign axi_stream_clean_tvalid = mem_writer.__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1.mem_writer__axi_st_clean_vld; + assign axi_stream_clean_tready = mem_writer.__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1.mem_writer__axi_st_clean_rdy; + + assign { axi_stream_padded_tdata, + axi_stream_padded_tstr, + axi_stream_padded_tkeep, + axi_stream_padded_tid, + axi_stream_padded_tdest, + axi_stream_padded_tlast} = mem_writer.__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4.mem_writer__axi_st_padded_data; + assign axi_stream_padded_tvalid = mem_writer.__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4.mem_writer__axi_st_padded_vld; + assign axi_stream_padded_tready = mem_writer.__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4.mem_writer__axi_st_padded_rdy; + + mem_writer mem_writer ( + .clk(clk), + .rst(rst), + + // MemWriter Write Request + .mem_writer__req_in_r_data(req_data), + .mem_writer__req_in_r_vld (req_vld), + .mem_writer__req_in_r_rdy (req_rdy), + + // Data to write + .mem_writer__data_in_r_data(data_in_data), + .mem_writer__data_in_r_vld (data_in_vld), + .mem_writer__data_in_r_rdy (data_in_rdy), + + // Response channel + .mem_writer__resp_s_data(resp_data), + .mem_writer__resp_s_rdy (resp_rdy), + .mem_writer__resp_s_vld (resp_vld), + + // Memory AXI + .mem_writer__axi_w_s_data(axi_w_data), + .mem_writer__axi_w_s_vld (axi_w_vld), + .mem_writer__axi_w_s_rdy (axi_w_rdy), + + .mem_writer__axi_aw_s_data(axi_aw_data), + .mem_writer__axi_aw_s_vld (axi_aw_vld), + .mem_writer__axi_aw_s_rdy (axi_aw_rdy), + + .mem_writer__axi_b_r_data(axi_b_data), + .mem_writer__axi_b_r_vld (axi_b_vld), + .mem_writer__axi_b_r_rdy (axi_b_rdy) + ); + +endmodule : mem_writer_wrapper From 12bb81a30cd53691673aed1b75f00553884278ab Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Tue, 31 Dec 2024 15:55:34 +0100 Subject: [PATCH 04/30] xls/modules/zstd: expose fifo verilog module Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/BUILD | 2 ++ xls/modules/zstd/memory/BUILD | 2 ++ xls/modules/zstd/memory/mem_reader_cocotb_test.py | 1 + xls/modules/zstd/memory/mem_writer_cocotb_test.py | 1 + 4 files changed, 6 insertions(+) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 0f23226ba6..a46a35ea60 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -60,6 +60,8 @@ xls_dslx_test( tags = ["manual"], ) +exports_files(["xls_fifo_wrapper.sv"]) + xls_dslx_library( name = "buffer_dslx", srcs = [ diff --git a/xls/modules/zstd/memory/BUILD b/xls/modules/zstd/memory/BUILD index dec4e61348..84f9933b1d 100644 --- a/xls/modules/zstd/memory/BUILD +++ b/xls/modules/zstd/memory/BUILD @@ -554,6 +554,7 @@ py_test( data = [ ":mem_reader_adv.v", ":mem_reader_wrapper.v", + "//xls/modules/zstd:xls_fifo_wrapper.sv", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], @@ -816,6 +817,7 @@ py_test( data = [ ":mem_writer.v", ":mem_writer_wrapper.v", + "//xls/modules/zstd:xls_fifo_wrapper.sv", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], diff --git a/xls/modules/zstd/memory/mem_reader_cocotb_test.py b/xls/modules/zstd/memory/mem_reader_cocotb_test.py index 845a321159..36c90cea1d 100644 --- a/xls/modules/zstd/memory/mem_reader_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_reader_cocotb_test.py @@ -264,6 +264,7 @@ async def mem_reader_aligned_transfer_shorter_than_bus4(dut): toplevel = "mem_reader_wrapper" verilog_sources = [ + "xls/modules/zstd/xls_fifo_wrapper.sv", "xls/modules/zstd/memory/mem_reader_adv.v", "xls/modules/zstd/memory/mem_reader_wrapper.v", ] diff --git a/xls/modules/zstd/memory/mem_writer_cocotb_test.py b/xls/modules/zstd/memory/mem_writer_cocotb_test.py index 63d6e29cbf..b617c41fa2 100644 --- a/xls/modules/zstd/memory/mem_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_writer_cocotb_test.py @@ -442,6 +442,7 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): if __name__ == "__main__": toplevel = "mem_writer_wrapper" verilog_sources = [ + "xls/modules/zstd/xls_fifo_wrapper.sv", "xls/modules/zstd/memory/mem_writer.v", "xls/modules/zstd/memory/mem_writer_wrapper.v", ] From f138fbe4939e15d9caa1d6d3529ff0692225b879 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Wed, 9 Oct 2024 15:23:22 +0200 Subject: [PATCH 05/30] modules/zstd/cocotb: Add ZSTD frame generator library This reverts commit 04ad379225b706ddf492d440c673e77348d7a409. --- xls/modules/zstd/cocotb/BUILD | 9 +++++ xls/modules/zstd/cocotb/data_generator.py | 46 +++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 xls/modules/zstd/cocotb/data_generator.py diff --git a/xls/modules/zstd/cocotb/BUILD b/xls/modules/zstd/cocotb/BUILD index 23b1a843c3..cdb788d732 100644 --- a/xls/modules/zstd/cocotb/BUILD +++ b/xls/modules/zstd/cocotb/BUILD @@ -64,3 +64,12 @@ py_library( requirement("cocotb"), ], ) + +py_library( + name = "data_generator", + srcs = ["data_generator.py"], + deps = [ + "//xls/common:runfiles", + "@zstd//:decodecorpus", + ], +) diff --git a/xls/modules/zstd/cocotb/data_generator.py b/xls/modules/zstd/cocotb/data_generator.py new file mode 100644 index 0000000000..105a9a7ec7 --- /dev/null +++ b/xls/modules/zstd/cocotb/data_generator.py @@ -0,0 +1,46 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import Path +from enum import Enum + +from xls.common import runfiles +import subprocess + +class BlockType(Enum): + RAW = 0 + RLE = 1 + COMPRESSED = 2 + RANDOM = 3 + +def CallDecodecorpus(args): + decodecorpus = Path(runfiles.get_path("decodecorpus", repository = "zstd")) + cmd = args + cmd.insert(0, str(decodecorpus)) + cmd_concat = " ".join(cmd) + subprocess.run(cmd_concat, shell=True, check=True) + +def GenerateFrame(seed, btype, output_path): + args = [] + args.append("-s" + str(seed)) + if (btype != BlockType.RANDOM): + args.append("--block-type=" + str(btype.value)) + args.append("--content-size") + # Test payloads up to 16KB + args.append("--max-content-size-log=14") + args.append("-p" + output_path); + args.append("-vvvvvvv"); + + CallDecodecorpus(args) + From 811f5fe7fda04c5f75125a4cc3838de2f6036cfb Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Thu, 3 Oct 2024 14:15:33 +0200 Subject: [PATCH 06/30] dependency_support: Add zstandard python library Signed-off-by: Pawel Czarnecki --- dependency_support/pip_requirements.in | 1 + dependency_support/pip_requirements_lock.txt | 99 ++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/dependency_support/pip_requirements.in b/dependency_support/pip_requirements.in index ef46f4703a..683f77261d 100644 --- a/dependency_support/pip_requirements.in +++ b/dependency_support/pip_requirements.in @@ -17,6 +17,7 @@ pytest==8.2.2 cocotb==1.9.0 cocotbext-axi==0.1.24 cocotb_bus==0.2.1 +zstandard==0.23.0 # Note: numpy and scipy version availability seems to differ between Ubuntu # versions that we want to support (e.g. 18.04 vs 20.04), so we accept a diff --git a/dependency_support/pip_requirements_lock.txt b/dependency_support/pip_requirements_lock.txt index 9872e57406..b3f361a2a0 100644 --- a/dependency_support/pip_requirements_lock.txt +++ b/dependency_support/pip_requirements_lock.txt @@ -609,3 +609,102 @@ z3-solver==4.14.0.0 \ --hash=sha256:c10f899c6a876e3a50e9b2c4927604c2c3da3cca672b8ed3b7db1bc97259e47f \ --hash=sha256:e6ae32bc1cf4d25b96f790755d790a23118e8a09b9b6060e32238fe6ff43606d # via -r dependency_support/pip_requirements.in +zstandard==0.23.0 \ + --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ + --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \ + --hash=sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15 \ + --hash=sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072 \ + --hash=sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4 \ + --hash=sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e \ + --hash=sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26 \ + --hash=sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8 \ + --hash=sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5 \ + --hash=sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd \ + --hash=sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c \ + --hash=sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db \ + --hash=sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5 \ + --hash=sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc \ + --hash=sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152 \ + --hash=sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269 \ + --hash=sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045 \ + --hash=sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e \ + --hash=sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d \ + --hash=sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a \ + --hash=sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb \ + --hash=sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740 \ + --hash=sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105 \ + --hash=sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274 \ + --hash=sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2 \ + --hash=sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58 \ + --hash=sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b \ + --hash=sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4 \ + --hash=sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db \ + --hash=sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e \ + --hash=sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9 \ + --hash=sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0 \ + --hash=sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813 \ + --hash=sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e \ + --hash=sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512 \ + --hash=sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 \ + --hash=sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b \ + --hash=sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48 \ + --hash=sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a \ + --hash=sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772 \ + --hash=sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed \ + --hash=sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373 \ + --hash=sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea \ + --hash=sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd \ + --hash=sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f \ + --hash=sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc \ + --hash=sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 \ + --hash=sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2 \ + --hash=sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db \ + --hash=sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70 \ + --hash=sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259 \ + --hash=sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9 \ + --hash=sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700 \ + --hash=sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003 \ + --hash=sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba \ + --hash=sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a \ + --hash=sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c \ + --hash=sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90 \ + --hash=sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690 \ + --hash=sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f \ + --hash=sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840 \ + --hash=sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d \ + --hash=sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9 \ + --hash=sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35 \ + --hash=sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd \ + --hash=sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a \ + --hash=sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea \ + --hash=sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1 \ + --hash=sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573 \ + --hash=sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09 \ + --hash=sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094 \ + --hash=sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78 \ + --hash=sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9 \ + --hash=sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5 \ + --hash=sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9 \ + --hash=sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391 \ + --hash=sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847 \ + --hash=sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2 \ + --hash=sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c \ + --hash=sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2 \ + --hash=sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057 \ + --hash=sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20 \ + --hash=sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d \ + --hash=sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4 \ + --hash=sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54 \ + --hash=sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171 \ + --hash=sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e \ + --hash=sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160 \ + --hash=sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b \ + --hash=sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58 \ + --hash=sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8 \ + --hash=sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33 \ + --hash=sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a \ + --hash=sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880 \ + --hash=sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca \ + --hash=sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b \ + --hash=sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69 + # via -r dependency_support/pip_requirements.in From 2a71280af7e2fea1e6afd72880cf218b51434284 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Tue, 8 Oct 2024 17:31:43 +0200 Subject: [PATCH 07/30] modules/zstd: Add verilog simulation of the ZstdDecoder Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/BUILD | 209 ++++- xls/modules/zstd/arbiter.v | 159 ++++ xls/modules/zstd/axi_interconnect.v | 988 ++++++++++++++++++++ xls/modules/zstd/axi_interconnect_wrapper.v | 424 +++++++++ xls/modules/zstd/priority_encoder.v | 92 ++ xls/modules/zstd/zstd_dec_cocotb_test.py | 418 +++++++++ 6 files changed, 2288 insertions(+), 2 deletions(-) create mode 100644 xls/modules/zstd/arbiter.v create mode 100644 xls/modules/zstd/axi_interconnect.v create mode 100644 xls/modules/zstd/axi_interconnect_wrapper.v create mode 100644 xls/modules/zstd/priority_encoder.v create mode 100644 xls/modules/zstd/zstd_dec_cocotb_test.py diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index a46a35ea60..420569a42b 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -18,6 +18,7 @@ load("@rules_hdl//place_and_route:build_defs.bzl", "place_and_route") load("@rules_hdl//synthesis:build_defs.bzl", "benchmark_synth", "synthesize_rtl") load("@rules_hdl//verilog:providers.bzl", "verilog_library") +load("@xls_pip_deps//:requirements.bzl", "requirement") load( "//xls/build_rules:xls_build_defs.bzl", "xls_benchmark_ir", @@ -60,8 +61,6 @@ xls_dslx_test( tags = ["manual"], ) -exports_files(["xls_fifo_wrapper.sv"]) - xls_dslx_library( name = "buffer_dslx", srcs = [ @@ -1495,6 +1494,101 @@ xls_dslx_test( deps = zstd_dec_deps, ) +ZSTD_DEC_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { + "module_name": "ZstdDecoder", + "clock_period_ps": "0", + "pipeline_stages": "16", + "flop_inputs_kind": "skid", + "flop_outputs_kind": "skid", + "worst_case_throughput": "6", + "materialize_internal_fifos": "false", # TODO: remove once this option works with loopback channels + "ram_configurations": ",".join([ + ",".join([ + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "history_buffer_ram{}".format(num), + rd_req = "zstd_dec__ram_rd_req_{}_s".format(num), + rd_resp = "zstd_dec__ram_rd_resp_{}_r".format(num), + wr_req = "zstd_dec__ram_wr_req_{}_s".format(num), + wr_resp = "zstd_dec__ram_wr_resp_{}_r".format(num), + ) + for num in range(8) + ]), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "dpd_ram", + rd_req = "zstd_dec__dpd_rd_req_s", + rd_resp = "zstd_dec__dpd_rd_resp_r", + wr_req = "zstd_dec__dpd_wr_req_s", + wr_resp = "zstd_dec__dpd_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "fse_tmp_ram", + rd_req = "zstd_dec__tmp_rd_req_s", + rd_resp = "zstd_dec__tmp_rd_resp_r", + wr_req = "zstd_dec__tmp_wr_req_s", + wr_resp = "zstd_dec__tmp_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "fse_tmp2_ram", + rd_req = "zstd_dec__tmp2_rd_req_s", + rd_resp = "zstd_dec__tmp2_rd_resp_r", + wr_req = "zstd_dec__tmp2_wr_req_s", + wr_resp = "zstd_dec__tmp2_wr_resp_r", + ), + ",".join([ + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "fse_lookup_ram{}".format(num), + rd_req = "zstd_dec__fse_rd_req_s__{}".format(num), + rd_resp = "zstd_dec__fse_rd_resp_r__{}".format(num), + wr_req = "zstd_dec__fse_wr_req_s__{}".format(num), + wr_resp = "zstd_dec__fse_wr_resp_r__{}".format(num), + ) + for num in range(6) + ]), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "huffman_literals_prescan_ram", + rd_req = "zstd_dec__huffman_lit_prescan_mem_rd_req_s", + rd_resp = "zstd_dec__huffman_lit_prescan_mem_rd_resp_r", + wr_req = "zstd_dec__huffman_lit_prescan_mem_wr_req_s", + wr_resp = "zstd_dec__huffman_lit_prescan_mem_wr_resp_r", + ), + # FIXME: Enable once HuffmanLiteralsDecoder has states independent of data read from RAM + #"{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + # latency = 5, + # ram_name = "huffman_literals_weights_ram", + # rd_req = "zstd_dec__huffman_lit_weights_mem_rd_req_s", + # rd_resp = "zstd_dec__huffman_lit_weights_mem_rd_resp_r", + # wr_req = "zstd_dec__huffman_lit_weights_mem_wr_req_s", + # wr_resp = "zstd_dec__huffman_lit_weights_mem_wr_resp_r", + #), + ",".join([ + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 5, + ram_name = "literals_buffer_ram{}".format(num), + rd_req = "zstd_dec__litbuf_rd_req_s__{}".format(num), + rd_resp = "zstd_dec__litbuf_rd_resp_r__{}".format(num), + wr_req = "zstd_dec__litbuf_wr_req_s__{}".format(num), + wr_resp = "zstd_dec__litbuf_wr_resp_r__{}".format(num), + ) + for num in range(8) + ]), + ]), +} + +xls_dslx_verilog( + name = "zstd_dec_verilog", + codegen_args = ZSTD_DEC_CODEGEN_ARGS, + dslx_top = "ZstdDecoderInst", + library = ":zstd_dec_dslx", + tags = ["manual"], + verilog_file = "zstd_dec.v", +) + ZSTD_DEC_INTERNAL_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { "module_name": "ZstdDecoderInternal", "pipeline_stages": "2", @@ -1554,6 +1648,82 @@ place_and_route( target_die_utilization_percentage = "10", ) +verilog_library( + name = "zstd_dec_verilog_lib", + srcs = [ + ":zstd_dec.v", + ], + tags = ["manual"], +) + +synthesize_rtl( + name = "zstd_dec_synth_asap7", + standard_cells = "@org_theopenroadproject_asap7sc7p5t_28//:asap7-sc7p5t_rev28_rvt", + tags = ["manual"], + top_module = "ZstdDecoder", + deps = [ + ":zstd_dec_verilog_lib", + "//xls/modules/zstd/rtl:xls_fifo_wrapper_verilog_lib", + ], +) + +benchmark_synth( + name = "zstd_dec_benchmark_synth", + synth_target = ":zstd_dec_synth_asap7", + tags = ["manual"], +) + +#place_and_route( +# name = "zstd_dec_place_and_route", +# clock_period = CLOCK_PERIOD_PS, +# core_padding_microns = 2, +# min_pin_distance = "0.4", +# placement_density = "0.1", +# stop_after_step = "global_routing", +# synthesized_rtl = ":zstd_dec_synth_asap7", +# tags = ["manual"], +# target_die_utilization_percentage = "1", +#) + +py_test( + name = "zstd_dec_cocotb_test", + srcs = ["zstd_dec_cocotb_test.py"], + data = [ + ":zstd_dec.v", + "//xls/modules/zstd/external:arbiter.v", + "//xls/modules/zstd/external:axi_crossbar.v", + "//xls/modules/zstd/external:axi_crossbar_addr.v", + "//xls/modules/zstd/external:axi_crossbar_rd.v", + "//xls/modules/zstd/external:axi_crossbar_wr.v", + "//xls/modules/zstd/external:axi_crossbar_wrapper.v", + "//xls/modules/zstd/external:axi_register_rd.v", + "//xls/modules/zstd/external:axi_register_wr.v", + "//xls/modules/zstd/external:priority_encoder.v", + "//xls/modules/zstd/rtl:zstd_dec_wrapper.sv", + "@com_icarus_iverilog//:iverilog", + "@com_icarus_iverilog//:vvp", + ], + env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, + imports = ["."], + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("cocotb"), + requirement("cocotbext-axi"), + requirement("pytest"), + requirement("zstandard"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:channel", + "//xls/modules/zstd/cocotb:data_generator", + "//xls/modules/zstd/cocotb:memory", + "//xls/modules/zstd/cocotb:utils", + "//xls/modules/zstd/cocotb:xlsstruct", + "@abseil-py//absl:app", + "@abseil-py//absl/flags", + "@com_google_protobuf//:protobuf_python", + ], +) + xls_dslx_library( name = "comp_lookup_dec_dslx", srcs = [ @@ -3531,3 +3701,38 @@ xls_dslx_test( name = "refilling_shift_buffer_mux_dslx_test", library = ":refilling_shift_buffer_mux_dslx", ) + +py_test( + name = "zstd_dec_cocotb_test", + srcs = ["zstd_dec_cocotb_test.py"], + data = [ + ":arbiter.v", + ":axi_interconnect.v", + ":axi_interconnect_wrapper.v", + ":priority_encoder.v", + ":xls_fifo_wrapper.sv", + ":zstd_dec.v", + ":zstd_dec_wrapper.sv", + "@com_icarus_iverilog//:iverilog", + "@com_icarus_iverilog//:vvp", + ], + env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, + imports = ["."], + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("cocotb"), + requirement("cocotbext-axi"), + requirement("pytest"), + requirement("zstandard"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:channel", + "//xls/modules/zstd/cocotb:data_generator", + "//xls/modules/zstd/cocotb:memory", + "//xls/modules/zstd/cocotb:utils", + "//xls/modules/zstd/cocotb:xlsstruct", + "@com_google_absl_py//absl:app", + "@com_google_absl_py//absl/flags", + "@com_google_protobuf//:protobuf_python", + ], +) diff --git a/xls/modules/zstd/arbiter.v b/xls/modules/zstd/arbiter.v new file mode 100644 index 0000000000..cfac70d1c6 --- /dev/null +++ b/xls/modules/zstd/arbiter.v @@ -0,0 +1,159 @@ +/* + +Copyright (c) 2014-2021 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * Arbiter module + */ +module arbiter # +( + parameter PORTS = 4, + // select round robin arbitration + parameter ARB_TYPE_ROUND_ROBIN = 0, + // blocking arbiter enable + parameter ARB_BLOCK = 0, + // block on acknowledge assert when nonzero, request deassert when 0 + parameter ARB_BLOCK_ACK = 1, + // LSB priority selection + parameter ARB_LSB_HIGH_PRIORITY = 0 +) +( + input wire clk, + input wire rst, + + input wire [PORTS-1:0] request, + input wire [PORTS-1:0] acknowledge, + + output wire [PORTS-1:0] grant, + output wire grant_valid, + output wire [$clog2(PORTS)-1:0] grant_encoded +); + +reg [PORTS-1:0] grant_reg = 0, grant_next; +reg grant_valid_reg = 0, grant_valid_next; +reg [$clog2(PORTS)-1:0] grant_encoded_reg = 0, grant_encoded_next; + +assign grant_valid = grant_valid_reg; +assign grant = grant_reg; +assign grant_encoded = grant_encoded_reg; + +wire request_valid; +wire [$clog2(PORTS)-1:0] request_index; +wire [PORTS-1:0] request_mask; + +priority_encoder #( + .WIDTH(PORTS), + .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) +) +priority_encoder_inst ( + .input_unencoded(request), + .output_valid(request_valid), + .output_encoded(request_index), + .output_unencoded(request_mask) +); + +reg [PORTS-1:0] mask_reg = 0, mask_next; + +wire masked_request_valid; +wire [$clog2(PORTS)-1:0] masked_request_index; +wire [PORTS-1:0] masked_request_mask; + +priority_encoder #( + .WIDTH(PORTS), + .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) +) +priority_encoder_masked ( + .input_unencoded(request & mask_reg), + .output_valid(masked_request_valid), + .output_encoded(masked_request_index), + .output_unencoded(masked_request_mask) +); + +always @* begin + grant_next = 0; + grant_valid_next = 0; + grant_encoded_next = 0; + mask_next = mask_reg; + + if (ARB_BLOCK && !ARB_BLOCK_ACK && grant_reg & request) begin + // granted request still asserted; hold it + grant_valid_next = grant_valid_reg; + grant_next = grant_reg; + grant_encoded_next = grant_encoded_reg; + end else if (ARB_BLOCK && ARB_BLOCK_ACK && grant_valid && !(grant_reg & acknowledge)) begin + // granted request not yet acknowledged; hold it + grant_valid_next = grant_valid_reg; + grant_next = grant_reg; + grant_encoded_next = grant_encoded_reg; + end else if (request_valid) begin + if (ARB_TYPE_ROUND_ROBIN) begin + if (masked_request_valid) begin + grant_valid_next = 1; + grant_next = masked_request_mask; + grant_encoded_next = masked_request_index; + if (ARB_LSB_HIGH_PRIORITY) begin + mask_next = {PORTS{1'b1}} << (masked_request_index + 1); + end else begin + mask_next = {PORTS{1'b1}} >> (PORTS - masked_request_index); + end + end else begin + grant_valid_next = 1; + grant_next = request_mask; + grant_encoded_next = request_index; + if (ARB_LSB_HIGH_PRIORITY) begin + mask_next = {PORTS{1'b1}} << (request_index + 1); + end else begin + mask_next = {PORTS{1'b1}} >> (PORTS - request_index); + end + end + end else begin + grant_valid_next = 1; + grant_next = request_mask; + grant_encoded_next = request_index; + end + end +end + +always @(posedge clk) begin + if (rst) begin + grant_reg <= 0; + grant_valid_reg <= 0; + grant_encoded_reg <= 0; + mask_reg <= 0; + end else begin + grant_reg <= grant_next; + grant_valid_reg <= grant_valid_next; + grant_encoded_reg <= grant_encoded_next; + mask_reg <= mask_next; + end +end + +endmodule + +`resetall diff --git a/xls/modules/zstd/axi_interconnect.v b/xls/modules/zstd/axi_interconnect.v new file mode 100644 index 0000000000..14256ad7de --- /dev/null +++ b/xls/modules/zstd/axi_interconnect.v @@ -0,0 +1,988 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 interconnect + */ +module axi_interconnect # +( + // Number of AXI inputs (slave interfaces) + parameter S_COUNT = 4, + // Number of AXI outputs (master interfaces) + parameter M_COUNT = 4, + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Width of ID signal + parameter ID_WIDTH = 8, + // Propagate awuser signal + parameter AWUSER_ENABLE = 0, + // Width of awuser signal + parameter AWUSER_WIDTH = 1, + // Propagate wuser signal + parameter WUSER_ENABLE = 0, + // Width of wuser signal + parameter WUSER_WIDTH = 1, + // Propagate buser signal + parameter BUSER_ENABLE = 0, + // Width of buser signal + parameter BUSER_WIDTH = 1, + // Propagate aruser signal + parameter ARUSER_ENABLE = 0, + // Width of aruser signal + parameter ARUSER_WIDTH = 1, + // Propagate ruser signal + parameter RUSER_ENABLE = 0, + // Width of ruser signal + parameter RUSER_WIDTH = 1, + // Propagate ID field + parameter FORWARD_ID = 0, + // Number of regions per master interface + parameter M_REGIONS = 1, + // Master interface base addresses + // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits + // set to zero for default addressing based on M_ADDR_WIDTH + parameter M_BASE_ADDR = 0, + // Master interface address widths + // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits + parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, + // Read connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}}, + // Write connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}}, + // Secure master (fail operations based on awprot/arprot) + // M_COUNT bits + parameter M_SECURE = {M_COUNT{1'b0}} +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interfaces + */ + input wire [S_COUNT*ID_WIDTH-1:0] s_axi_awid, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr, + input wire [S_COUNT*8-1:0] s_axi_awlen, + input wire [S_COUNT*3-1:0] s_axi_awsize, + input wire [S_COUNT*2-1:0] s_axi_awburst, + input wire [S_COUNT-1:0] s_axi_awlock, + input wire [S_COUNT*4-1:0] s_axi_awcache, + input wire [S_COUNT*3-1:0] s_axi_awprot, + input wire [S_COUNT*4-1:0] s_axi_awqos, + input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser, + input wire [S_COUNT-1:0] s_axi_awvalid, + output wire [S_COUNT-1:0] s_axi_awready, + input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata, + input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb, + input wire [S_COUNT-1:0] s_axi_wlast, + input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser, + input wire [S_COUNT-1:0] s_axi_wvalid, + output wire [S_COUNT-1:0] s_axi_wready, + output wire [S_COUNT*ID_WIDTH-1:0] s_axi_bid, + output wire [S_COUNT*2-1:0] s_axi_bresp, + output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser, + output wire [S_COUNT-1:0] s_axi_bvalid, + input wire [S_COUNT-1:0] s_axi_bready, + input wire [S_COUNT*ID_WIDTH-1:0] s_axi_arid, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr, + input wire [S_COUNT*8-1:0] s_axi_arlen, + input wire [S_COUNT*3-1:0] s_axi_arsize, + input wire [S_COUNT*2-1:0] s_axi_arburst, + input wire [S_COUNT-1:0] s_axi_arlock, + input wire [S_COUNT*4-1:0] s_axi_arcache, + input wire [S_COUNT*3-1:0] s_axi_arprot, + input wire [S_COUNT*4-1:0] s_axi_arqos, + input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser, + input wire [S_COUNT-1:0] s_axi_arvalid, + output wire [S_COUNT-1:0] s_axi_arready, + output wire [S_COUNT*ID_WIDTH-1:0] s_axi_rid, + output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata, + output wire [S_COUNT*2-1:0] s_axi_rresp, + output wire [S_COUNT-1:0] s_axi_rlast, + output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser, + output wire [S_COUNT-1:0] s_axi_rvalid, + input wire [S_COUNT-1:0] s_axi_rready, + + /* + * AXI master interfaces + */ + output wire [M_COUNT*ID_WIDTH-1:0] m_axi_awid, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [M_COUNT*8-1:0] m_axi_awlen, + output wire [M_COUNT*3-1:0] m_axi_awsize, + output wire [M_COUNT*2-1:0] m_axi_awburst, + output wire [M_COUNT-1:0] m_axi_awlock, + output wire [M_COUNT*4-1:0] m_axi_awcache, + output wire [M_COUNT*3-1:0] m_axi_awprot, + output wire [M_COUNT*4-1:0] m_axi_awqos, + output wire [M_COUNT*4-1:0] m_axi_awregion, + output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser, + output wire [M_COUNT-1:0] m_axi_awvalid, + input wire [M_COUNT-1:0] m_axi_awready, + output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata, + output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb, + output wire [M_COUNT-1:0] m_axi_wlast, + output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser, + output wire [M_COUNT-1:0] m_axi_wvalid, + input wire [M_COUNT-1:0] m_axi_wready, + input wire [M_COUNT*ID_WIDTH-1:0] m_axi_bid, + input wire [M_COUNT*2-1:0] m_axi_bresp, + input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser, + input wire [M_COUNT-1:0] m_axi_bvalid, + output wire [M_COUNT-1:0] m_axi_bready, + output wire [M_COUNT*ID_WIDTH-1:0] m_axi_arid, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr, + output wire [M_COUNT*8-1:0] m_axi_arlen, + output wire [M_COUNT*3-1:0] m_axi_arsize, + output wire [M_COUNT*2-1:0] m_axi_arburst, + output wire [M_COUNT-1:0] m_axi_arlock, + output wire [M_COUNT*4-1:0] m_axi_arcache, + output wire [M_COUNT*3-1:0] m_axi_arprot, + output wire [M_COUNT*4-1:0] m_axi_arqos, + output wire [M_COUNT*4-1:0] m_axi_arregion, + output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser, + output wire [M_COUNT-1:0] m_axi_arvalid, + input wire [M_COUNT-1:0] m_axi_arready, + input wire [M_COUNT*ID_WIDTH-1:0] m_axi_rid, + input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata, + input wire [M_COUNT*2-1:0] m_axi_rresp, + input wire [M_COUNT-1:0] m_axi_rlast, + input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser, + input wire [M_COUNT-1:0] m_axi_rvalid, + output wire [M_COUNT-1:0] m_axi_rready +); + +parameter CL_S_COUNT = $clog2(S_COUNT); +parameter CL_M_COUNT = $clog2(M_COUNT); + +parameter AUSER_WIDTH = AWUSER_WIDTH > ARUSER_WIDTH ? AWUSER_WIDTH : ARUSER_WIDTH; + +// default address computation +function [M_COUNT*M_REGIONS*ADDR_WIDTH-1:0] calcBaseAddrs(input [31:0] dummy); + integer i; + reg [ADDR_WIDTH-1:0] base; + reg [ADDR_WIDTH-1:0] width; + reg [ADDR_WIDTH-1:0] size; + reg [ADDR_WIDTH-1:0] mask; + begin + calcBaseAddrs = {M_COUNT*M_REGIONS*ADDR_WIDTH{1'b0}}; + base = 0; + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + width = M_ADDR_WIDTH[i*32 +: 32]; + mask = {ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - width); + size = mask + 1; + if (width > 0) begin + if ((base & mask) != 0) begin + base = base + size - (base & mask); // align + end + calcBaseAddrs[i * ADDR_WIDTH +: ADDR_WIDTH] = base; + base = base + size; // increment + end + end + end +endfunction + +parameter M_BASE_ADDR_INT = M_BASE_ADDR ? M_BASE_ADDR : calcBaseAddrs(0); + +integer i, j; + +// check configuration +initial begin + if (M_REGIONS < 1 || M_REGIONS > 16) begin + $error("Error: M_REGIONS must be between 1 and 16 (instance %m)"); + $finish; + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin + $error("Error: address width out of range (instance %m)"); + $finish; + end + end + + $display("Addressing configuration for axi_interconnect instance %m"); + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32]) begin + $display("%2d (%2d): %x / %02d -- %x-%x", + i/M_REGIONS, i%M_REGIONS, + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[i*32 +: 32], + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + ); + end + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if ((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & (2**M_ADDR_WIDTH[i*32 +: 32]-1)) != 0) begin + $display("Region not aligned:"); + $display("%2d (%2d): %x / %2d -- %x-%x", + i/M_REGIONS, i%M_REGIONS, + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[i*32 +: 32], + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + ); + $error("Error: address range not aligned (instance %m)"); + $finish; + end + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + for (j = i+1; j < M_COUNT*M_REGIONS; j = j + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && M_ADDR_WIDTH[j*32 +: 32]) begin + if (((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])))) + && ((M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin + $display("Overlapping regions:"); + $display("%2d (%2d): %x / %2d -- %x-%x", + i/M_REGIONS, i%M_REGIONS, + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[i*32 +: 32], + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + ); + $display("%2d (%2d): %x / %2d -- %x-%x", + j/M_REGIONS, j%M_REGIONS, + M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[j*32 +: 32], + M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]), + M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])) + ); + $error("Error: address ranges overlap (instance %m)"); + $finish; + end + end + end + end +end + +localparam [2:0] + STATE_IDLE = 3'd0, + STATE_DECODE = 3'd1, + STATE_WRITE = 3'd2, + STATE_WRITE_RESP = 3'd3, + STATE_WRITE_DROP = 3'd4, + STATE_READ = 3'd5, + STATE_READ_DROP = 3'd6, + STATE_WAIT_IDLE = 3'd7; + +reg [2:0] state_reg = STATE_IDLE, state_next; + +reg match; + +reg [CL_M_COUNT-1:0] m_select_reg = 2'd0, m_select_next; +reg [ID_WIDTH-1:0] axi_id_reg = {ID_WIDTH{1'b0}}, axi_id_next; +reg [ADDR_WIDTH-1:0] axi_addr_reg = {ADDR_WIDTH{1'b0}}, axi_addr_next; +reg axi_addr_valid_reg = 1'b0, axi_addr_valid_next; +reg [7:0] axi_len_reg = 8'd0, axi_len_next; +reg [2:0] axi_size_reg = 3'd0, axi_size_next; +reg [1:0] axi_burst_reg = 2'd0, axi_burst_next; +reg axi_lock_reg = 1'b0, axi_lock_next; +reg [3:0] axi_cache_reg = 4'd0, axi_cache_next; +reg [2:0] axi_prot_reg = 3'b000, axi_prot_next; +reg [3:0] axi_qos_reg = 4'd0, axi_qos_next; +reg [3:0] axi_region_reg = 4'd0, axi_region_next; +reg [AUSER_WIDTH-1:0] axi_auser_reg = {AUSER_WIDTH{1'b0}}, axi_auser_next; +reg [1:0] axi_bresp_reg = 2'b00, axi_bresp_next; +reg [BUSER_WIDTH-1:0] axi_buser_reg = {BUSER_WIDTH{1'b0}}, axi_buser_next; + +reg [S_COUNT-1:0] s_axi_awready_reg = 0, s_axi_awready_next; +reg [S_COUNT-1:0] s_axi_wready_reg = 0, s_axi_wready_next; +reg [S_COUNT-1:0] s_axi_bvalid_reg = 0, s_axi_bvalid_next; +reg [S_COUNT-1:0] s_axi_arready_reg = 0, s_axi_arready_next; + +reg [M_COUNT-1:0] m_axi_awvalid_reg = 0, m_axi_awvalid_next; +reg [M_COUNT-1:0] m_axi_bready_reg = 0, m_axi_bready_next; +reg [M_COUNT-1:0] m_axi_arvalid_reg = 0, m_axi_arvalid_next; +reg [M_COUNT-1:0] m_axi_rready_reg = 0, m_axi_rready_next; + +// internal datapath +reg [ID_WIDTH-1:0] s_axi_rid_int; +reg [DATA_WIDTH-1:0] s_axi_rdata_int; +reg [1:0] s_axi_rresp_int; +reg s_axi_rlast_int; +reg [RUSER_WIDTH-1:0] s_axi_ruser_int; +reg s_axi_rvalid_int; +reg s_axi_rready_int_reg = 1'b0; +wire s_axi_rready_int_early; + +reg [DATA_WIDTH-1:0] m_axi_wdata_int; +reg [STRB_WIDTH-1:0] m_axi_wstrb_int; +reg m_axi_wlast_int; +reg [WUSER_WIDTH-1:0] m_axi_wuser_int; +reg m_axi_wvalid_int; +reg m_axi_wready_int_reg = 1'b0; +wire m_axi_wready_int_early; + +assign s_axi_awready = s_axi_awready_reg; +assign s_axi_wready = s_axi_wready_reg; +assign s_axi_bid = {S_COUNT{axi_id_reg}}; +assign s_axi_bresp = {S_COUNT{axi_bresp_reg}}; +assign s_axi_buser = {S_COUNT{BUSER_ENABLE ? axi_buser_reg : {BUSER_WIDTH{1'b0}}}}; +assign s_axi_bvalid = s_axi_bvalid_reg; +assign s_axi_arready = s_axi_arready_reg; + +assign m_axi_awid = {M_COUNT{FORWARD_ID ? axi_id_reg : {ID_WIDTH{1'b0}}}}; +assign m_axi_awaddr = {M_COUNT{axi_addr_reg}}; +assign m_axi_awlen = {M_COUNT{axi_len_reg}}; +assign m_axi_awsize = {M_COUNT{axi_size_reg}}; +assign m_axi_awburst = {M_COUNT{axi_burst_reg}}; +assign m_axi_awlock = {M_COUNT{axi_lock_reg}}; +assign m_axi_awcache = {M_COUNT{axi_cache_reg}}; +assign m_axi_awprot = {M_COUNT{axi_prot_reg}}; +assign m_axi_awqos = {M_COUNT{axi_qos_reg}}; +assign m_axi_awregion = {M_COUNT{axi_region_reg}}; +assign m_axi_awuser = {M_COUNT{AWUSER_ENABLE ? axi_auser_reg[AWUSER_WIDTH-1:0] : {AWUSER_WIDTH{1'b0}}}}; +assign m_axi_awvalid = m_axi_awvalid_reg; +assign m_axi_bready = m_axi_bready_reg; +assign m_axi_arid = {M_COUNT{FORWARD_ID ? axi_id_reg : {ID_WIDTH{1'b0}}}}; +assign m_axi_araddr = {M_COUNT{axi_addr_reg}}; +assign m_axi_arlen = {M_COUNT{axi_len_reg}}; +assign m_axi_arsize = {M_COUNT{axi_size_reg}}; +assign m_axi_arburst = {M_COUNT{axi_burst_reg}}; +assign m_axi_arlock = {M_COUNT{axi_lock_reg}}; +assign m_axi_arcache = {M_COUNT{axi_cache_reg}}; +assign m_axi_arprot = {M_COUNT{axi_prot_reg}}; +assign m_axi_arqos = {M_COUNT{axi_qos_reg}}; +assign m_axi_arregion = {M_COUNT{axi_region_reg}}; +assign m_axi_aruser = {M_COUNT{ARUSER_ENABLE ? axi_auser_reg[ARUSER_WIDTH-1:0] : {ARUSER_WIDTH{1'b0}}}}; +assign m_axi_arvalid = m_axi_arvalid_reg; +assign m_axi_rready = m_axi_rready_reg; + +// slave side mux +wire [(CL_S_COUNT > 0 ? CL_S_COUNT-1 : 0):0] s_select; + +wire [ID_WIDTH-1:0] current_s_axi_awid = s_axi_awid[s_select*ID_WIDTH +: ID_WIDTH]; +wire [ADDR_WIDTH-1:0] current_s_axi_awaddr = s_axi_awaddr[s_select*ADDR_WIDTH +: ADDR_WIDTH]; +wire [7:0] current_s_axi_awlen = s_axi_awlen[s_select*8 +: 8]; +wire [2:0] current_s_axi_awsize = s_axi_awsize[s_select*3 +: 3]; +wire [1:0] current_s_axi_awburst = s_axi_awburst[s_select*2 +: 2]; +wire current_s_axi_awlock = s_axi_awlock[s_select]; +wire [3:0] current_s_axi_awcache = s_axi_awcache[s_select*4 +: 4]; +wire [2:0] current_s_axi_awprot = s_axi_awprot[s_select*3 +: 3]; +wire [3:0] current_s_axi_awqos = s_axi_awqos[s_select*4 +: 4]; +wire [AWUSER_WIDTH-1:0] current_s_axi_awuser = s_axi_awuser[s_select*AWUSER_WIDTH +: AWUSER_WIDTH]; +wire current_s_axi_awvalid = s_axi_awvalid[s_select]; +wire current_s_axi_awready = s_axi_awready[s_select]; +wire [DATA_WIDTH-1:0] current_s_axi_wdata = s_axi_wdata[s_select*DATA_WIDTH +: DATA_WIDTH]; +wire [STRB_WIDTH-1:0] current_s_axi_wstrb = s_axi_wstrb[s_select*STRB_WIDTH +: STRB_WIDTH]; +wire current_s_axi_wlast = s_axi_wlast[s_select]; +wire [WUSER_WIDTH-1:0] current_s_axi_wuser = s_axi_wuser[s_select*WUSER_WIDTH +: WUSER_WIDTH]; +wire current_s_axi_wvalid = s_axi_wvalid[s_select]; +wire current_s_axi_wready = s_axi_wready[s_select]; +wire [ID_WIDTH-1:0] current_s_axi_bid = s_axi_bid[s_select*ID_WIDTH +: ID_WIDTH]; +wire [1:0] current_s_axi_bresp = s_axi_bresp[s_select*2 +: 2]; +wire [BUSER_WIDTH-1:0] current_s_axi_buser = s_axi_buser[s_select*BUSER_WIDTH +: BUSER_WIDTH]; +wire current_s_axi_bvalid = s_axi_bvalid[s_select]; +wire current_s_axi_bready = s_axi_bready[s_select]; +wire [ID_WIDTH-1:0] current_s_axi_arid = s_axi_arid[s_select*ID_WIDTH +: ID_WIDTH]; +wire [ADDR_WIDTH-1:0] current_s_axi_araddr = s_axi_araddr[s_select*ADDR_WIDTH +: ADDR_WIDTH]; +wire [7:0] current_s_axi_arlen = s_axi_arlen[s_select*8 +: 8]; +wire [2:0] current_s_axi_arsize = s_axi_arsize[s_select*3 +: 3]; +wire [1:0] current_s_axi_arburst = s_axi_arburst[s_select*2 +: 2]; +wire current_s_axi_arlock = s_axi_arlock[s_select]; +wire [3:0] current_s_axi_arcache = s_axi_arcache[s_select*4 +: 4]; +wire [2:0] current_s_axi_arprot = s_axi_arprot[s_select*3 +: 3]; +wire [3:0] current_s_axi_arqos = s_axi_arqos[s_select*4 +: 4]; +wire [ARUSER_WIDTH-1:0] current_s_axi_aruser = s_axi_aruser[s_select*ARUSER_WIDTH +: ARUSER_WIDTH]; +wire current_s_axi_arvalid = s_axi_arvalid[s_select]; +wire current_s_axi_arready = s_axi_arready[s_select]; +wire [ID_WIDTH-1:0] current_s_axi_rid = s_axi_rid[s_select*ID_WIDTH +: ID_WIDTH]; +wire [DATA_WIDTH-1:0] current_s_axi_rdata = s_axi_rdata[s_select*DATA_WIDTH +: DATA_WIDTH]; +wire [1:0] current_s_axi_rresp = s_axi_rresp[s_select*2 +: 2]; +wire current_s_axi_rlast = s_axi_rlast[s_select]; +wire [RUSER_WIDTH-1:0] current_s_axi_ruser = s_axi_ruser[s_select*RUSER_WIDTH +: RUSER_WIDTH]; +wire current_s_axi_rvalid = s_axi_rvalid[s_select]; +wire current_s_axi_rready = s_axi_rready[s_select]; + +// master side mux +wire [ID_WIDTH-1:0] current_m_axi_awid = m_axi_awid[m_select_reg*ID_WIDTH +: ID_WIDTH]; +wire [ADDR_WIDTH-1:0] current_m_axi_awaddr = m_axi_awaddr[m_select_reg*ADDR_WIDTH +: ADDR_WIDTH]; +wire [7:0] current_m_axi_awlen = m_axi_awlen[m_select_reg*8 +: 8]; +wire [2:0] current_m_axi_awsize = m_axi_awsize[m_select_reg*3 +: 3]; +wire [1:0] current_m_axi_awburst = m_axi_awburst[m_select_reg*2 +: 2]; +wire current_m_axi_awlock = m_axi_awlock[m_select_reg]; +wire [3:0] current_m_axi_awcache = m_axi_awcache[m_select_reg*4 +: 4]; +wire [2:0] current_m_axi_awprot = m_axi_awprot[m_select_reg*3 +: 3]; +wire [3:0] current_m_axi_awqos = m_axi_awqos[m_select_reg*4 +: 4]; +wire [3:0] current_m_axi_awregion = m_axi_awregion[m_select_reg*4 +: 4]; +wire [AWUSER_WIDTH-1:0] current_m_axi_awuser = m_axi_awuser[m_select_reg*AWUSER_WIDTH +: AWUSER_WIDTH]; +wire current_m_axi_awvalid = m_axi_awvalid[m_select_reg]; +wire current_m_axi_awready = m_axi_awready[m_select_reg]; +wire [DATA_WIDTH-1:0] current_m_axi_wdata = m_axi_wdata[m_select_reg*DATA_WIDTH +: DATA_WIDTH]; +wire [STRB_WIDTH-1:0] current_m_axi_wstrb = m_axi_wstrb[m_select_reg*STRB_WIDTH +: STRB_WIDTH]; +wire current_m_axi_wlast = m_axi_wlast[m_select_reg]; +wire [WUSER_WIDTH-1:0] current_m_axi_wuser = m_axi_wuser[m_select_reg*WUSER_WIDTH +: WUSER_WIDTH]; +wire current_m_axi_wvalid = m_axi_wvalid[m_select_reg]; +wire current_m_axi_wready = m_axi_wready[m_select_reg]; +wire [ID_WIDTH-1:0] current_m_axi_bid = m_axi_bid[m_select_reg*ID_WIDTH +: ID_WIDTH]; +wire [1:0] current_m_axi_bresp = m_axi_bresp[m_select_reg*2 +: 2]; +wire [BUSER_WIDTH-1:0] current_m_axi_buser = m_axi_buser[m_select_reg*BUSER_WIDTH +: BUSER_WIDTH]; +wire current_m_axi_bvalid = m_axi_bvalid[m_select_reg]; +wire current_m_axi_bready = m_axi_bready[m_select_reg]; +wire [ID_WIDTH-1:0] current_m_axi_arid = m_axi_arid[m_select_reg*ID_WIDTH +: ID_WIDTH]; +wire [ADDR_WIDTH-1:0] current_m_axi_araddr = m_axi_araddr[m_select_reg*ADDR_WIDTH +: ADDR_WIDTH]; +wire [7:0] current_m_axi_arlen = m_axi_arlen[m_select_reg*8 +: 8]; +wire [2:0] current_m_axi_arsize = m_axi_arsize[m_select_reg*3 +: 3]; +wire [1:0] current_m_axi_arburst = m_axi_arburst[m_select_reg*2 +: 2]; +wire current_m_axi_arlock = m_axi_arlock[m_select_reg]; +wire [3:0] current_m_axi_arcache = m_axi_arcache[m_select_reg*4 +: 4]; +wire [2:0] current_m_axi_arprot = m_axi_arprot[m_select_reg*3 +: 3]; +wire [3:0] current_m_axi_arqos = m_axi_arqos[m_select_reg*4 +: 4]; +wire [3:0] current_m_axi_arregion = m_axi_arregion[m_select_reg*4 +: 4]; +wire [ARUSER_WIDTH-1:0] current_m_axi_aruser = m_axi_aruser[m_select_reg*ARUSER_WIDTH +: ARUSER_WIDTH]; +wire current_m_axi_arvalid = m_axi_arvalid[m_select_reg]; +wire current_m_axi_arready = m_axi_arready[m_select_reg]; +wire [ID_WIDTH-1:0] current_m_axi_rid = m_axi_rid[m_select_reg*ID_WIDTH +: ID_WIDTH]; +wire [DATA_WIDTH-1:0] current_m_axi_rdata = m_axi_rdata[m_select_reg*DATA_WIDTH +: DATA_WIDTH]; +wire [1:0] current_m_axi_rresp = m_axi_rresp[m_select_reg*2 +: 2]; +wire current_m_axi_rlast = m_axi_rlast[m_select_reg]; +wire [RUSER_WIDTH-1:0] current_m_axi_ruser = m_axi_ruser[m_select_reg*RUSER_WIDTH +: RUSER_WIDTH]; +wire current_m_axi_rvalid = m_axi_rvalid[m_select_reg]; +wire current_m_axi_rready = m_axi_rready[m_select_reg]; + +// arbiter instance +wire [S_COUNT*2-1:0] request; +wire [S_COUNT*2-1:0] acknowledge; +wire [S_COUNT*2-1:0] grant; +wire grant_valid; +wire [CL_S_COUNT:0] grant_encoded; + +wire read = grant_encoded[0]; +assign s_select = grant_encoded >> 1; + +arbiter #( + .PORTS(S_COUNT*2), + .ARB_TYPE_ROUND_ROBIN(1), + .ARB_BLOCK(1), + .ARB_BLOCK_ACK(1), + .ARB_LSB_HIGH_PRIORITY(1) +) +arb_inst ( + .clk(clk), + .rst(rst), + .request(request), + .acknowledge(acknowledge), + .grant(grant), + .grant_valid(grant_valid), + .grant_encoded(grant_encoded) +); + +genvar n; + +// request generation +generate +for (n = 0; n < S_COUNT; n = n + 1) begin + assign request[2*n] = s_axi_awvalid[n]; + assign request[2*n+1] = s_axi_arvalid[n]; +end +endgenerate + +// acknowledge generation +generate +for (n = 0; n < S_COUNT; n = n + 1) begin + assign acknowledge[2*n] = grant[2*n] && s_axi_bvalid[n] && s_axi_bready[n]; + assign acknowledge[2*n+1] = grant[2*n+1] && s_axi_rvalid[n] && s_axi_rready[n] && s_axi_rlast[n]; +end +endgenerate + +always @* begin + state_next = STATE_IDLE; + + match = 1'b0; + + m_select_next = m_select_reg; + axi_id_next = axi_id_reg; + axi_addr_next = axi_addr_reg; + axi_addr_valid_next = axi_addr_valid_reg; + axi_len_next = axi_len_reg; + axi_size_next = axi_size_reg; + axi_burst_next = axi_burst_reg; + axi_lock_next = axi_lock_reg; + axi_cache_next = axi_cache_reg; + axi_prot_next = axi_prot_reg; + axi_qos_next = axi_qos_reg; + axi_region_next = axi_region_reg; + axi_auser_next = axi_auser_reg; + axi_bresp_next = axi_bresp_reg; + axi_buser_next = axi_buser_reg; + + s_axi_awready_next = 0; + s_axi_wready_next = 0; + s_axi_bvalid_next = s_axi_bvalid_reg & ~s_axi_bready; + s_axi_arready_next = 0; + + m_axi_awvalid_next = m_axi_awvalid_reg & ~m_axi_awready; + m_axi_bready_next = 0; + m_axi_arvalid_next = m_axi_arvalid_reg & ~m_axi_arready; + m_axi_rready_next = 0; + + s_axi_rid_int = axi_id_reg; + s_axi_rdata_int = current_m_axi_rdata; + s_axi_rresp_int = current_m_axi_rresp; + s_axi_rlast_int = current_m_axi_rlast; + s_axi_ruser_int = current_m_axi_ruser; + s_axi_rvalid_int = 1'b0; + + m_axi_wdata_int = current_s_axi_wdata; + m_axi_wstrb_int = current_s_axi_wstrb; + m_axi_wlast_int = current_s_axi_wlast; + m_axi_wuser_int = current_s_axi_wuser; + m_axi_wvalid_int = 1'b0; + + case (state_reg) + STATE_IDLE: begin + // idle state; wait for arbitration + + if (grant_valid) begin + + axi_addr_valid_next = 1'b1; + + if (read) begin + // reading + axi_addr_next = current_s_axi_araddr; + axi_prot_next = current_s_axi_arprot; + axi_id_next = current_s_axi_arid; + axi_addr_next = current_s_axi_araddr; + axi_len_next = current_s_axi_arlen; + axi_size_next = current_s_axi_arsize; + axi_burst_next = current_s_axi_arburst; + axi_lock_next = current_s_axi_arlock; + axi_cache_next = current_s_axi_arcache; + axi_prot_next = current_s_axi_arprot; + axi_qos_next = current_s_axi_arqos; + axi_auser_next = current_s_axi_aruser; + s_axi_arready_next[s_select] = 1'b1; + end else begin + // writing + axi_addr_next = current_s_axi_awaddr; + axi_prot_next = current_s_axi_awprot; + axi_id_next = current_s_axi_awid; + axi_addr_next = current_s_axi_awaddr; + axi_len_next = current_s_axi_awlen; + axi_size_next = current_s_axi_awsize; + axi_burst_next = current_s_axi_awburst; + axi_lock_next = current_s_axi_awlock; + axi_cache_next = current_s_axi_awcache; + axi_prot_next = current_s_axi_awprot; + axi_qos_next = current_s_axi_awqos; + axi_auser_next = current_s_axi_awuser; + s_axi_awready_next[s_select] = 1'b1; + end + + state_next = STATE_DECODE; + end else begin + state_next = STATE_IDLE; + end + end + STATE_DECODE: begin + // decode state; determine master interface + + match = 1'b0; + for (i = 0; i < M_COUNT; i = i + 1) begin + for (j = 0; j < M_REGIONS; j = j + 1) begin + if (M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32] && (!M_SECURE[i] || !axi_prot_reg[1]) && ((read ? M_CONNECT_READ : M_CONNECT_WRITE) & (1 << (s_select+i*S_COUNT))) && (axi_addr_reg >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32]) == (M_BASE_ADDR_INT[(i*M_REGIONS+j)*ADDR_WIDTH +: ADDR_WIDTH] >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32])) begin + m_select_next = i; + axi_region_next = j; + match = 1'b1; + end + end + end + + if (match) begin + if (read) begin + // reading + m_axi_rready_next[m_select_reg] = s_axi_rready_int_early; + state_next = STATE_READ; + end else begin + // writing + s_axi_wready_next[s_select] = m_axi_wready_int_early; + state_next = STATE_WRITE; + end + end else begin + // no match; return decode error + if (read) begin + // reading + state_next = STATE_READ_DROP; + end else begin + // writing + axi_bresp_next = 2'b11; + s_axi_wready_next[s_select] = 1'b1; + state_next = STATE_WRITE_DROP; + end + end + end + STATE_WRITE: begin + // write state; store and forward write data + s_axi_wready_next[s_select] = m_axi_wready_int_early; + + if (axi_addr_valid_reg) begin + m_axi_awvalid_next[m_select_reg] = 1'b1; + end + axi_addr_valid_next = 1'b0; + + if (current_s_axi_wready && current_s_axi_wvalid) begin + m_axi_wdata_int = current_s_axi_wdata; + m_axi_wstrb_int = current_s_axi_wstrb; + m_axi_wlast_int = current_s_axi_wlast; + m_axi_wuser_int = current_s_axi_wuser; + m_axi_wvalid_int = 1'b1; + + if (current_s_axi_wlast) begin + s_axi_wready_next[s_select] = 1'b0; + m_axi_bready_next[m_select_reg] = 1'b1; + state_next = STATE_WRITE_RESP; + end else begin + state_next = STATE_WRITE; + end + end else begin + state_next = STATE_WRITE; + end + end + STATE_WRITE_RESP: begin + // write response state; store and forward write response + m_axi_bready_next[m_select_reg] = 1'b1; + + if (current_m_axi_bready && current_m_axi_bvalid) begin + m_axi_bready_next[m_select_reg] = 1'b0; + axi_bresp_next = current_m_axi_bresp; + s_axi_bvalid_next[s_select] = 1'b1; + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_WRITE_RESP; + end + end + STATE_WRITE_DROP: begin + // write drop state; drop write data + s_axi_wready_next[s_select] = 1'b1; + + axi_addr_valid_next = 1'b0; + + if (current_s_axi_wready && current_s_axi_wvalid && current_s_axi_wlast) begin + s_axi_wready_next[s_select] = 1'b0; + s_axi_bvalid_next[s_select] = 1'b1; + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_WRITE_DROP; + end + end + STATE_READ: begin + // read state; store and forward read response + m_axi_rready_next[m_select_reg] = s_axi_rready_int_early; + + if (axi_addr_valid_reg) begin + m_axi_arvalid_next[m_select_reg] = 1'b1; + end + axi_addr_valid_next = 1'b0; + + if (current_m_axi_rready && current_m_axi_rvalid) begin + s_axi_rid_int = axi_id_reg; + s_axi_rdata_int = current_m_axi_rdata; + s_axi_rresp_int = current_m_axi_rresp; + s_axi_rlast_int = current_m_axi_rlast; + s_axi_ruser_int = current_m_axi_ruser; + s_axi_rvalid_int = 1'b1; + + if (current_m_axi_rlast) begin + m_axi_rready_next[m_select_reg] = 1'b0; + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_READ; + end + end else begin + state_next = STATE_READ; + end + end + STATE_READ_DROP: begin + // read drop state; generate decode error read response + + s_axi_rid_int = axi_id_reg; + s_axi_rdata_int = {DATA_WIDTH{1'b0}}; + s_axi_rresp_int = 2'b11; + s_axi_rlast_int = axi_len_reg == 0; + s_axi_ruser_int = {RUSER_WIDTH{1'b0}}; + s_axi_rvalid_int = 1'b1; + + if (s_axi_rready_int_reg) begin + axi_len_next = axi_len_reg - 1; + if (axi_len_reg == 0) begin + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_READ_DROP; + end + end else begin + state_next = STATE_READ_DROP; + end + end + STATE_WAIT_IDLE: begin + // wait for idle state; wait untl grant valid is deasserted + + if (!grant_valid || acknowledge) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_WAIT_IDLE; + end + end + endcase +end + +always @(posedge clk) begin + if (rst) begin + state_reg <= STATE_IDLE; + + s_axi_awready_reg <= 0; + s_axi_wready_reg <= 0; + s_axi_bvalid_reg <= 0; + s_axi_arready_reg <= 0; + + m_axi_awvalid_reg <= 0; + m_axi_bready_reg <= 0; + m_axi_arvalid_reg <= 0; + m_axi_rready_reg <= 0; + end else begin + state_reg <= state_next; + + s_axi_awready_reg <= s_axi_awready_next; + s_axi_wready_reg <= s_axi_wready_next; + s_axi_bvalid_reg <= s_axi_bvalid_next; + s_axi_arready_reg <= s_axi_arready_next; + + m_axi_awvalid_reg <= m_axi_awvalid_next; + m_axi_bready_reg <= m_axi_bready_next; + m_axi_arvalid_reg <= m_axi_arvalid_next; + m_axi_rready_reg <= m_axi_rready_next; + end + + m_select_reg <= m_select_next; + axi_id_reg <= axi_id_next; + axi_addr_reg <= axi_addr_next; + axi_addr_valid_reg <= axi_addr_valid_next; + axi_len_reg <= axi_len_next; + axi_size_reg <= axi_size_next; + axi_burst_reg <= axi_burst_next; + axi_lock_reg <= axi_lock_next; + axi_cache_reg <= axi_cache_next; + axi_prot_reg <= axi_prot_next; + axi_qos_reg <= axi_qos_next; + axi_region_reg <= axi_region_next; + axi_auser_reg <= axi_auser_next; + axi_bresp_reg <= axi_bresp_next; + axi_buser_reg <= axi_buser_next; +end + +// output datapath logic (R channel) +reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; +reg [1:0] s_axi_rresp_reg = 2'd0; +reg s_axi_rlast_reg = 1'b0; +reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = 1'b0; +reg [S_COUNT-1:0] s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next; + +reg [ID_WIDTH-1:0] temp_s_axi_rid_reg = {ID_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] temp_s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; +reg [1:0] temp_s_axi_rresp_reg = 2'd0; +reg temp_s_axi_rlast_reg = 1'b0; +reg [RUSER_WIDTH-1:0] temp_s_axi_ruser_reg = 1'b0; +reg temp_s_axi_rvalid_reg = 1'b0, temp_s_axi_rvalid_next; + +// datapath control +reg store_axi_r_int_to_output; +reg store_axi_r_int_to_temp; +reg store_axi_r_temp_to_output; + +assign s_axi_rid = {S_COUNT{s_axi_rid_reg}}; +assign s_axi_rdata = {S_COUNT{s_axi_rdata_reg}}; +assign s_axi_rresp = {S_COUNT{s_axi_rresp_reg}}; +assign s_axi_rlast = {S_COUNT{s_axi_rlast_reg}}; +assign s_axi_ruser = {S_COUNT{RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}}}}; +assign s_axi_rvalid = s_axi_rvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign s_axi_rready_int_early = current_s_axi_rready | (~temp_s_axi_rvalid_reg & (~current_s_axi_rvalid | ~s_axi_rvalid_int)); + +always @* begin + // transfer sink ready state to source + s_axi_rvalid_next = s_axi_rvalid_reg; + temp_s_axi_rvalid_next = temp_s_axi_rvalid_reg; + + store_axi_r_int_to_output = 1'b0; + store_axi_r_int_to_temp = 1'b0; + store_axi_r_temp_to_output = 1'b0; + + if (s_axi_rready_int_reg) begin + // input is ready + if (current_s_axi_rready | ~current_s_axi_rvalid) begin + // output is ready or currently not valid, transfer data to output + s_axi_rvalid_next[s_select] = s_axi_rvalid_int; + store_axi_r_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_s_axi_rvalid_next = s_axi_rvalid_int; + store_axi_r_int_to_temp = 1'b1; + end + end else if (current_s_axi_rready) begin + // input is not ready, but output is ready + s_axi_rvalid_next[s_select] = temp_s_axi_rvalid_reg; + temp_s_axi_rvalid_next = 1'b0; + store_axi_r_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_rvalid_reg <= 1'b0; + s_axi_rready_int_reg <= 1'b0; + temp_s_axi_rvalid_reg <= 1'b0; + end else begin + s_axi_rvalid_reg <= s_axi_rvalid_next; + s_axi_rready_int_reg <= s_axi_rready_int_early; + temp_s_axi_rvalid_reg <= temp_s_axi_rvalid_next; + end + + // datapath + if (store_axi_r_int_to_output) begin + s_axi_rid_reg <= s_axi_rid_int; + s_axi_rdata_reg <= s_axi_rdata_int; + s_axi_rresp_reg <= s_axi_rresp_int; + s_axi_rlast_reg <= s_axi_rlast_int; + s_axi_ruser_reg <= s_axi_ruser_int; + end else if (store_axi_r_temp_to_output) begin + s_axi_rid_reg <= temp_s_axi_rid_reg; + s_axi_rdata_reg <= temp_s_axi_rdata_reg; + s_axi_rresp_reg <= temp_s_axi_rresp_reg; + s_axi_rlast_reg <= temp_s_axi_rlast_reg; + s_axi_ruser_reg <= temp_s_axi_ruser_reg; + end + + if (store_axi_r_int_to_temp) begin + temp_s_axi_rid_reg <= s_axi_rid_int; + temp_s_axi_rdata_reg <= s_axi_rdata_int; + temp_s_axi_rresp_reg <= s_axi_rresp_int; + temp_s_axi_rlast_reg <= s_axi_rlast_int; + temp_s_axi_ruser_reg <= s_axi_ruser_int; + end +end + +// output datapath logic (W channel) +reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; +reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; +reg m_axi_wlast_reg = 1'b0; +reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = 1'b0; +reg [M_COUNT-1:0] m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next; + +reg [DATA_WIDTH-1:0] temp_m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; +reg [STRB_WIDTH-1:0] temp_m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; +reg temp_m_axi_wlast_reg = 1'b0; +reg [WUSER_WIDTH-1:0] temp_m_axi_wuser_reg = 1'b0; +reg temp_m_axi_wvalid_reg = 1'b0, temp_m_axi_wvalid_next; + +// datapath control +reg store_axi_w_int_to_output; +reg store_axi_w_int_to_temp; +reg store_axi_w_temp_to_output; + +assign m_axi_wdata = {M_COUNT{m_axi_wdata_reg}}; +assign m_axi_wstrb = {M_COUNT{m_axi_wstrb_reg}}; +assign m_axi_wlast = {M_COUNT{m_axi_wlast_reg}}; +assign m_axi_wuser = {M_COUNT{WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}}}}; +assign m_axi_wvalid = m_axi_wvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign m_axi_wready_int_early = current_m_axi_wready | (~temp_m_axi_wvalid_reg & (~current_m_axi_wvalid | ~m_axi_wvalid_int)); + +always @* begin + // transfer sink ready state to source + m_axi_wvalid_next = m_axi_wvalid_reg; + temp_m_axi_wvalid_next = temp_m_axi_wvalid_reg; + + store_axi_w_int_to_output = 1'b0; + store_axi_w_int_to_temp = 1'b0; + store_axi_w_temp_to_output = 1'b0; + + if (m_axi_wready_int_reg) begin + // input is ready + if (current_m_axi_wready | ~current_m_axi_wvalid) begin + // output is ready or currently not valid, transfer data to output + m_axi_wvalid_next[m_select_reg] = m_axi_wvalid_int; + store_axi_w_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axi_wvalid_next = m_axi_wvalid_int; + store_axi_w_int_to_temp = 1'b1; + end + end else if (current_m_axi_wready) begin + // input is not ready, but output is ready + m_axi_wvalid_next[m_select_reg] = temp_m_axi_wvalid_reg; + temp_m_axi_wvalid_next = 1'b0; + store_axi_w_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + m_axi_wvalid_reg <= 1'b0; + m_axi_wready_int_reg <= 1'b0; + temp_m_axi_wvalid_reg <= 1'b0; + end else begin + m_axi_wvalid_reg <= m_axi_wvalid_next; + m_axi_wready_int_reg <= m_axi_wready_int_early; + temp_m_axi_wvalid_reg <= temp_m_axi_wvalid_next; + end + + // datapath + if (store_axi_w_int_to_output) begin + m_axi_wdata_reg <= m_axi_wdata_int; + m_axi_wstrb_reg <= m_axi_wstrb_int; + m_axi_wlast_reg <= m_axi_wlast_int; + m_axi_wuser_reg <= m_axi_wuser_int; + end else if (store_axi_w_temp_to_output) begin + m_axi_wdata_reg <= temp_m_axi_wdata_reg; + m_axi_wstrb_reg <= temp_m_axi_wstrb_reg; + m_axi_wlast_reg <= temp_m_axi_wlast_reg; + m_axi_wuser_reg <= temp_m_axi_wuser_reg; + end + + if (store_axi_w_int_to_temp) begin + temp_m_axi_wdata_reg <= m_axi_wdata_int; + temp_m_axi_wstrb_reg <= m_axi_wstrb_int; + temp_m_axi_wlast_reg <= m_axi_wlast_int; + temp_m_axi_wuser_reg <= m_axi_wuser_int; + end +end + +endmodule + +`resetall diff --git a/xls/modules/zstd/axi_interconnect_wrapper.v b/xls/modules/zstd/axi_interconnect_wrapper.v new file mode 100644 index 0000000000..50017314f9 --- /dev/null +++ b/xls/modules/zstd/axi_interconnect_wrapper.v @@ -0,0 +1,424 @@ +/* + +Copyright (c) 2020 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 4x1 interconnect (wrapper) + */ +module axi_interconnect_wrapper # +( + parameter DATA_WIDTH = 32, + parameter ADDR_WIDTH = 32, + parameter STRB_WIDTH = (DATA_WIDTH/8), + parameter ID_WIDTH = 8, + parameter AWUSER_ENABLE = 0, + parameter AWUSER_WIDTH = 1, + parameter WUSER_ENABLE = 0, + parameter WUSER_WIDTH = 1, + parameter BUSER_ENABLE = 0, + parameter BUSER_WIDTH = 1, + parameter ARUSER_ENABLE = 0, + parameter ARUSER_WIDTH = 1, + parameter RUSER_ENABLE = 0, + parameter RUSER_WIDTH = 1, + parameter FORWARD_ID = 0, + parameter M_REGIONS = 1, + parameter M00_BASE_ADDR = 0, + parameter M00_ADDR_WIDTH = {M_REGIONS{32'd24}}, + parameter M00_CONNECT_READ = 4'b1111, + parameter M00_CONNECT_WRITE = 4'b1111, + parameter M00_SECURE = 1'b0 +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interface + */ + input wire [ID_WIDTH-1:0] s00_axi_awid, + input wire [ADDR_WIDTH-1:0] s00_axi_awaddr, + input wire [7:0] s00_axi_awlen, + input wire [2:0] s00_axi_awsize, + input wire [1:0] s00_axi_awburst, + input wire s00_axi_awlock, + input wire [3:0] s00_axi_awcache, + input wire [2:0] s00_axi_awprot, + input wire [3:0] s00_axi_awqos, + input wire [AWUSER_WIDTH-1:0] s00_axi_awuser, + input wire s00_axi_awvalid, + output wire s00_axi_awready, + input wire [DATA_WIDTH-1:0] s00_axi_wdata, + input wire [STRB_WIDTH-1:0] s00_axi_wstrb, + input wire s00_axi_wlast, + input wire [WUSER_WIDTH-1:0] s00_axi_wuser, + input wire s00_axi_wvalid, + output wire s00_axi_wready, + output wire [ID_WIDTH-1:0] s00_axi_bid, + output wire [1:0] s00_axi_bresp, + output wire [BUSER_WIDTH-1:0] s00_axi_buser, + output wire s00_axi_bvalid, + input wire s00_axi_bready, + input wire [ID_WIDTH-1:0] s00_axi_arid, + input wire [ADDR_WIDTH-1:0] s00_axi_araddr, + input wire [7:0] s00_axi_arlen, + input wire [2:0] s00_axi_arsize, + input wire [1:0] s00_axi_arburst, + input wire s00_axi_arlock, + input wire [3:0] s00_axi_arcache, + input wire [2:0] s00_axi_arprot, + input wire [3:0] s00_axi_arqos, + input wire [ARUSER_WIDTH-1:0] s00_axi_aruser, + input wire s00_axi_arvalid, + output wire s00_axi_arready, + output wire [ID_WIDTH-1:0] s00_axi_rid, + output wire [DATA_WIDTH-1:0] s00_axi_rdata, + output wire [1:0] s00_axi_rresp, + output wire s00_axi_rlast, + output wire [RUSER_WIDTH-1:0] s00_axi_ruser, + output wire s00_axi_rvalid, + input wire s00_axi_rready, + + input wire [ID_WIDTH-1:0] s01_axi_awid, + input wire [ADDR_WIDTH-1:0] s01_axi_awaddr, + input wire [7:0] s01_axi_awlen, + input wire [2:0] s01_axi_awsize, + input wire [1:0] s01_axi_awburst, + input wire s01_axi_awlock, + input wire [3:0] s01_axi_awcache, + input wire [2:0] s01_axi_awprot, + input wire [3:0] s01_axi_awqos, + input wire [AWUSER_WIDTH-1:0] s01_axi_awuser, + input wire s01_axi_awvalid, + output wire s01_axi_awready, + input wire [DATA_WIDTH-1:0] s01_axi_wdata, + input wire [STRB_WIDTH-1:0] s01_axi_wstrb, + input wire s01_axi_wlast, + input wire [WUSER_WIDTH-1:0] s01_axi_wuser, + input wire s01_axi_wvalid, + output wire s01_axi_wready, + output wire [ID_WIDTH-1:0] s01_axi_bid, + output wire [1:0] s01_axi_bresp, + output wire [BUSER_WIDTH-1:0] s01_axi_buser, + output wire s01_axi_bvalid, + input wire s01_axi_bready, + input wire [ID_WIDTH-1:0] s01_axi_arid, + input wire [ADDR_WIDTH-1:0] s01_axi_araddr, + input wire [7:0] s01_axi_arlen, + input wire [2:0] s01_axi_arsize, + input wire [1:0] s01_axi_arburst, + input wire s01_axi_arlock, + input wire [3:0] s01_axi_arcache, + input wire [2:0] s01_axi_arprot, + input wire [3:0] s01_axi_arqos, + input wire [ARUSER_WIDTH-1:0] s01_axi_aruser, + input wire s01_axi_arvalid, + output wire s01_axi_arready, + output wire [ID_WIDTH-1:0] s01_axi_rid, + output wire [DATA_WIDTH-1:0] s01_axi_rdata, + output wire [1:0] s01_axi_rresp, + output wire s01_axi_rlast, + output wire [RUSER_WIDTH-1:0] s01_axi_ruser, + output wire s01_axi_rvalid, + input wire s01_axi_rready, + + input wire [ID_WIDTH-1:0] s02_axi_awid, + input wire [ADDR_WIDTH-1:0] s02_axi_awaddr, + input wire [7:0] s02_axi_awlen, + input wire [2:0] s02_axi_awsize, + input wire [1:0] s02_axi_awburst, + input wire s02_axi_awlock, + input wire [3:0] s02_axi_awcache, + input wire [2:0] s02_axi_awprot, + input wire [3:0] s02_axi_awqos, + input wire [AWUSER_WIDTH-1:0] s02_axi_awuser, + input wire s02_axi_awvalid, + output wire s02_axi_awready, + input wire [DATA_WIDTH-1:0] s02_axi_wdata, + input wire [STRB_WIDTH-1:0] s02_axi_wstrb, + input wire s02_axi_wlast, + input wire [WUSER_WIDTH-1:0] s02_axi_wuser, + input wire s02_axi_wvalid, + output wire s02_axi_wready, + output wire [ID_WIDTH-1:0] s02_axi_bid, + output wire [1:0] s02_axi_bresp, + output wire [BUSER_WIDTH-1:0] s02_axi_buser, + output wire s02_axi_bvalid, + input wire s02_axi_bready, + input wire [ID_WIDTH-1:0] s02_axi_arid, + input wire [ADDR_WIDTH-1:0] s02_axi_araddr, + input wire [7:0] s02_axi_arlen, + input wire [2:0] s02_axi_arsize, + input wire [1:0] s02_axi_arburst, + input wire s02_axi_arlock, + input wire [3:0] s02_axi_arcache, + input wire [2:0] s02_axi_arprot, + input wire [3:0] s02_axi_arqos, + input wire [ARUSER_WIDTH-1:0] s02_axi_aruser, + input wire s02_axi_arvalid, + output wire s02_axi_arready, + output wire [ID_WIDTH-1:0] s02_axi_rid, + output wire [DATA_WIDTH-1:0] s02_axi_rdata, + output wire [1:0] s02_axi_rresp, + output wire s02_axi_rlast, + output wire [RUSER_WIDTH-1:0] s02_axi_ruser, + output wire s02_axi_rvalid, + input wire s02_axi_rready, + + input wire [ID_WIDTH-1:0] s03_axi_awid, + input wire [ADDR_WIDTH-1:0] s03_axi_awaddr, + input wire [7:0] s03_axi_awlen, + input wire [2:0] s03_axi_awsize, + input wire [1:0] s03_axi_awburst, + input wire s03_axi_awlock, + input wire [3:0] s03_axi_awcache, + input wire [2:0] s03_axi_awprot, + input wire [3:0] s03_axi_awqos, + input wire [AWUSER_WIDTH-1:0] s03_axi_awuser, + input wire s03_axi_awvalid, + output wire s03_axi_awready, + input wire [DATA_WIDTH-1:0] s03_axi_wdata, + input wire [STRB_WIDTH-1:0] s03_axi_wstrb, + input wire s03_axi_wlast, + input wire [WUSER_WIDTH-1:0] s03_axi_wuser, + input wire s03_axi_wvalid, + output wire s03_axi_wready, + output wire [ID_WIDTH-1:0] s03_axi_bid, + output wire [1:0] s03_axi_bresp, + output wire [BUSER_WIDTH-1:0] s03_axi_buser, + output wire s03_axi_bvalid, + input wire s03_axi_bready, + input wire [ID_WIDTH-1:0] s03_axi_arid, + input wire [ADDR_WIDTH-1:0] s03_axi_araddr, + input wire [7:0] s03_axi_arlen, + input wire [2:0] s03_axi_arsize, + input wire [1:0] s03_axi_arburst, + input wire s03_axi_arlock, + input wire [3:0] s03_axi_arcache, + input wire [2:0] s03_axi_arprot, + input wire [3:0] s03_axi_arqos, + input wire [ARUSER_WIDTH-1:0] s03_axi_aruser, + input wire s03_axi_arvalid, + output wire s03_axi_arready, + output wire [ID_WIDTH-1:0] s03_axi_rid, + output wire [DATA_WIDTH-1:0] s03_axi_rdata, + output wire [1:0] s03_axi_rresp, + output wire s03_axi_rlast, + output wire [RUSER_WIDTH-1:0] s03_axi_ruser, + output wire s03_axi_rvalid, + input wire s03_axi_rready, + + /* + * AXI master interface + */ + output wire [ID_WIDTH-1:0] m00_axi_awid, + output wire [ADDR_WIDTH-1:0] m00_axi_awaddr, + output wire [7:0] m00_axi_awlen, + output wire [2:0] m00_axi_awsize, + output wire [1:0] m00_axi_awburst, + output wire m00_axi_awlock, + output wire [3:0] m00_axi_awcache, + output wire [2:0] m00_axi_awprot, + output wire [3:0] m00_axi_awqos, + output wire [3:0] m00_axi_awregion, + output wire [AWUSER_WIDTH-1:0] m00_axi_awuser, + output wire m00_axi_awvalid, + input wire m00_axi_awready, + output wire [DATA_WIDTH-1:0] m00_axi_wdata, + output wire [STRB_WIDTH-1:0] m00_axi_wstrb, + output wire m00_axi_wlast, + output wire [WUSER_WIDTH-1:0] m00_axi_wuser, + output wire m00_axi_wvalid, + input wire m00_axi_wready, + input wire [ID_WIDTH-1:0] m00_axi_bid, + input wire [1:0] m00_axi_bresp, + input wire [BUSER_WIDTH-1:0] m00_axi_buser, + input wire m00_axi_bvalid, + output wire m00_axi_bready, + output wire [ID_WIDTH-1:0] m00_axi_arid, + output wire [ADDR_WIDTH-1:0] m00_axi_araddr, + output wire [7:0] m00_axi_arlen, + output wire [2:0] m00_axi_arsize, + output wire [1:0] m00_axi_arburst, + output wire m00_axi_arlock, + output wire [3:0] m00_axi_arcache, + output wire [2:0] m00_axi_arprot, + output wire [3:0] m00_axi_arqos, + output wire [3:0] m00_axi_arregion, + output wire [ARUSER_WIDTH-1:0] m00_axi_aruser, + output wire m00_axi_arvalid, + input wire m00_axi_arready, + input wire [ID_WIDTH-1:0] m00_axi_rid, + input wire [DATA_WIDTH-1:0] m00_axi_rdata, + input wire [1:0] m00_axi_rresp, + input wire m00_axi_rlast, + input wire [RUSER_WIDTH-1:0] m00_axi_ruser, + input wire m00_axi_rvalid, + output wire m00_axi_rready +); + +localparam S_COUNT = 4; +localparam M_COUNT = 1; + +// parameter sizing helpers +function [ADDR_WIDTH*M_REGIONS-1:0] w_a_r(input [ADDR_WIDTH*M_REGIONS-1:0] val); + w_a_r = val; +endfunction + +function [32*M_REGIONS-1:0] w_32_r(input [32*M_REGIONS-1:0] val); + w_32_r = val; +endfunction + +function [S_COUNT-1:0] w_s(input [S_COUNT-1:0] val); + w_s = val; +endfunction + +function w_1(input val); + w_1 = val; +endfunction + +axi_interconnect #( + .S_COUNT(S_COUNT), + .M_COUNT(M_COUNT), + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .ID_WIDTH(ID_WIDTH), + .AWUSER_ENABLE(AWUSER_ENABLE), + .AWUSER_WIDTH(AWUSER_WIDTH), + .WUSER_ENABLE(WUSER_ENABLE), + .WUSER_WIDTH(WUSER_WIDTH), + .BUSER_ENABLE(BUSER_ENABLE), + .BUSER_WIDTH(BUSER_WIDTH), + .ARUSER_ENABLE(ARUSER_ENABLE), + .ARUSER_WIDTH(ARUSER_WIDTH), + .RUSER_ENABLE(RUSER_ENABLE), + .RUSER_WIDTH(RUSER_WIDTH), + .FORWARD_ID(FORWARD_ID), + .M_REGIONS(M_REGIONS), + .M_BASE_ADDR({ w_a_r(M00_BASE_ADDR) }), + .M_ADDR_WIDTH({ w_32_r(M00_ADDR_WIDTH) }), + .M_CONNECT_READ({ w_s(M00_CONNECT_READ) }), + .M_CONNECT_WRITE({ w_s(M00_CONNECT_WRITE) }), + .M_SECURE({ w_1(M00_SECURE) }) +) +axi_interconnect_inst ( + .clk(clk), + .rst(rst), + .s_axi_awid({ s03_axi_awid, s02_axi_awid, s01_axi_awid, s00_axi_awid }), + .s_axi_awaddr({ s03_axi_awaddr, s02_axi_awaddr, s01_axi_awaddr, s00_axi_awaddr }), + .s_axi_awlen({ s03_axi_awlen, s02_axi_awlen, s01_axi_awlen, s00_axi_awlen }), + .s_axi_awsize({ s03_axi_awsize, s02_axi_awsize, s01_axi_awsize, s00_axi_awsize }), + .s_axi_awburst({ s03_axi_awburst, s02_axi_awburst, s01_axi_awburst, s00_axi_awburst }), + .s_axi_awlock({ s03_axi_awlock, s02_axi_awlock, s01_axi_awlock, s00_axi_awlock }), + .s_axi_awcache({ s03_axi_awcache, s02_axi_awcache, s01_axi_awcache, s00_axi_awcache }), + .s_axi_awprot({ s03_axi_awprot, s02_axi_awprot, s01_axi_awprot, s00_axi_awprot }), + .s_axi_awqos({ s03_axi_awqos, s02_axi_awqos, s01_axi_awqos, s00_axi_awqos }), + .s_axi_awuser({ s03_axi_awuser, s02_axi_awuser, s01_axi_awuser, s00_axi_awuser }), + .s_axi_awvalid({ s03_axi_awvalid, s02_axi_awvalid, s01_axi_awvalid, s00_axi_awvalid }), + .s_axi_awready({ s03_axi_awready, s02_axi_awready, s01_axi_awready, s00_axi_awready }), + .s_axi_wdata({ s03_axi_wdata, s02_axi_wdata, s01_axi_wdata, s00_axi_wdata }), + .s_axi_wstrb({ s03_axi_wstrb, s02_axi_wstrb, s01_axi_wstrb, s00_axi_wstrb }), + .s_axi_wlast({ s03_axi_wlast, s02_axi_wlast, s01_axi_wlast, s00_axi_wlast }), + .s_axi_wuser({ s03_axi_wuser, s02_axi_wuser, s01_axi_wuser, s00_axi_wuser }), + .s_axi_wvalid({ s03_axi_wvalid, s02_axi_wvalid, s01_axi_wvalid, s00_axi_wvalid }), + .s_axi_wready({ s03_axi_wready, s02_axi_wready, s01_axi_wready, s00_axi_wready }), + .s_axi_bid({ s03_axi_bid, s02_axi_bid, s01_axi_bid, s00_axi_bid }), + .s_axi_bresp({ s03_axi_bresp, s02_axi_bresp, s01_axi_bresp, s00_axi_bresp }), + .s_axi_buser({ s03_axi_buser, s02_axi_buser, s01_axi_buser, s00_axi_buser }), + .s_axi_bvalid({ s03_axi_bvalid, s02_axi_bvalid, s01_axi_bvalid, s00_axi_bvalid }), + .s_axi_bready({ s03_axi_bready, s02_axi_bready, s01_axi_bready, s00_axi_bready }), + .s_axi_arid({ s03_axi_arid, s02_axi_arid, s01_axi_arid, s00_axi_arid }), + .s_axi_araddr({ s03_axi_araddr, s02_axi_araddr, s01_axi_araddr, s00_axi_araddr }), + .s_axi_arlen({ s03_axi_arlen, s02_axi_arlen, s01_axi_arlen, s00_axi_arlen }), + .s_axi_arsize({ s03_axi_arsize, s02_axi_arsize, s01_axi_arsize, s00_axi_arsize }), + .s_axi_arburst({ s03_axi_arburst, s02_axi_arburst, s01_axi_arburst, s00_axi_arburst }), + .s_axi_arlock({ s03_axi_arlock, s02_axi_arlock, s01_axi_arlock, s00_axi_arlock }), + .s_axi_arcache({ s03_axi_arcache, s02_axi_arcache, s01_axi_arcache, s00_axi_arcache }), + .s_axi_arprot({ s03_axi_arprot, s02_axi_arprot, s01_axi_arprot, s00_axi_arprot }), + .s_axi_arqos({ s03_axi_arqos, s02_axi_arqos, s01_axi_arqos, s00_axi_arqos }), + .s_axi_aruser({ s03_axi_aruser, s02_axi_aruser, s01_axi_aruser, s00_axi_aruser }), + .s_axi_arvalid({ s03_axi_arvalid, s02_axi_arvalid, s01_axi_arvalid, s00_axi_arvalid }), + .s_axi_arready({ s03_axi_arready, s02_axi_arready, s01_axi_arready, s00_axi_arready }), + .s_axi_rid({ s03_axi_rid, s02_axi_rid, s01_axi_rid, s00_axi_rid }), + .s_axi_rdata({ s03_axi_rdata, s02_axi_rdata, s01_axi_rdata, s00_axi_rdata }), + .s_axi_rresp({ s03_axi_rresp, s02_axi_rresp, s01_axi_rresp, s00_axi_rresp }), + .s_axi_rlast({ s03_axi_rlast, s02_axi_rlast, s01_axi_rlast, s00_axi_rlast }), + .s_axi_ruser({ s03_axi_ruser, s02_axi_ruser, s01_axi_ruser, s00_axi_ruser }), + .s_axi_rvalid({ s03_axi_rvalid, s02_axi_rvalid, s01_axi_rvalid, s00_axi_rvalid }), + .s_axi_rready({ s03_axi_rready, s02_axi_rready, s01_axi_rready, s00_axi_rready }), + .m_axi_awid({ m00_axi_awid }), + .m_axi_awaddr({ m00_axi_awaddr }), + .m_axi_awlen({ m00_axi_awlen }), + .m_axi_awsize({ m00_axi_awsize }), + .m_axi_awburst({ m00_axi_awburst }), + .m_axi_awlock({ m00_axi_awlock }), + .m_axi_awcache({ m00_axi_awcache }), + .m_axi_awprot({ m00_axi_awprot }), + .m_axi_awqos({ m00_axi_awqos }), + .m_axi_awregion({ m00_axi_awregion }), + .m_axi_awuser({ m00_axi_awuser }), + .m_axi_awvalid({ m00_axi_awvalid }), + .m_axi_awready({ m00_axi_awready }), + .m_axi_wdata({ m00_axi_wdata }), + .m_axi_wstrb({ m00_axi_wstrb }), + .m_axi_wlast({ m00_axi_wlast }), + .m_axi_wuser({ m00_axi_wuser }), + .m_axi_wvalid({ m00_axi_wvalid }), + .m_axi_wready({ m00_axi_wready }), + .m_axi_bid({ m00_axi_bid }), + .m_axi_bresp({ m00_axi_bresp }), + .m_axi_buser({ m00_axi_buser }), + .m_axi_bvalid({ m00_axi_bvalid }), + .m_axi_bready({ m00_axi_bready }), + .m_axi_arid({ m00_axi_arid }), + .m_axi_araddr({ m00_axi_araddr }), + .m_axi_arlen({ m00_axi_arlen }), + .m_axi_arsize({ m00_axi_arsize }), + .m_axi_arburst({ m00_axi_arburst }), + .m_axi_arlock({ m00_axi_arlock }), + .m_axi_arcache({ m00_axi_arcache }), + .m_axi_arprot({ m00_axi_arprot }), + .m_axi_arqos({ m00_axi_arqos }), + .m_axi_arregion({ m00_axi_arregion }), + .m_axi_aruser({ m00_axi_aruser }), + .m_axi_arvalid({ m00_axi_arvalid }), + .m_axi_arready({ m00_axi_arready }), + .m_axi_rid({ m00_axi_rid }), + .m_axi_rdata({ m00_axi_rdata }), + .m_axi_rresp({ m00_axi_rresp }), + .m_axi_rlast({ m00_axi_rlast }), + .m_axi_ruser({ m00_axi_ruser }), + .m_axi_rvalid({ m00_axi_rvalid }), + .m_axi_rready({ m00_axi_rready }) +); + +endmodule + +`resetall diff --git a/xls/modules/zstd/priority_encoder.v b/xls/modules/zstd/priority_encoder.v new file mode 100644 index 0000000000..cf82512ba8 --- /dev/null +++ b/xls/modules/zstd/priority_encoder.v @@ -0,0 +1,92 @@ +/* + +Copyright (c) 2014-2021 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * Priority encoder module + */ +module priority_encoder # +( + parameter WIDTH = 4, + // LSB priority selection + parameter LSB_HIGH_PRIORITY = 0 +) +( + input wire [WIDTH-1:0] input_unencoded, + output wire output_valid, + output wire [$clog2(WIDTH)-1:0] output_encoded, + output wire [WIDTH-1:0] output_unencoded +); + +parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1; +parameter W = 2**LEVELS; + +// pad input to even power of two +wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded}; + +wire [W/2-1:0] stage_valid[LEVELS-1:0]; +wire [W/2-1:0] stage_enc[LEVELS-1:0]; + +generate + genvar l, n; + + // process input bits; generate valid bit and encoded bit for each pair + for (n = 0; n < W/2; n = n + 1) begin : loop_in + assign stage_valid[0][n] = |input_padded[n*2+1:n*2]; + if (LSB_HIGH_PRIORITY) begin + // bit 0 is highest priority + assign stage_enc[0][n] = !input_padded[n*2+0]; + end else begin + // bit 0 is lowest priority + assign stage_enc[0][n] = input_padded[n*2+1]; + end + end + + // compress down to single valid bit and encoded bus + for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels + for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress + assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2]; + if (LSB_HIGH_PRIORITY) begin + // bit 0 is highest priority + assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]}; + end else begin + // bit 0 is lowest priority + assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]}; + end + end + end +endgenerate + +assign output_valid = stage_valid[LEVELS-1]; +assign output_encoded = stage_enc[LEVELS-1]; +assign output_unencoded = 1 << output_encoded; + +endmodule + +`resetall diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py new file mode 100644 index 0000000000..ff9fd5afff --- /dev/null +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -0,0 +1,418 @@ +#!/usr/bin/env python +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from enum import Enum +from pathlib import Path +import tempfile + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import ClockCycles, Event +from cocotb.binary import BinaryValue +from cocotb_bus.scoreboard import Scoreboard + +from cocotbext.axi.axi_master import AxiMaster +from cocotbext.axi.axi_channels import AxiAWBus, AxiWBus, AxiBBus, AxiWriteBus, AxiARBus, AxiRBus, AxiReadBus, AxiBus, AxiBTransaction, AxiBSource, AxiBSink, AxiBMonitor, AxiRTransaction, AxiRSource, AxiRSink, AxiRMonitor +from cocotbext.axi.axi_ram import AxiRam +from cocotbext.axi.sparse_memory import SparseMemory + +import zstandard + +from xls.common import runfiles +from xls.modules.zstd.cocotb.channel import ( + XLSChannel, + XLSChannelDriver, + XLSChannelMonitor, +) +from xls.modules.zstd.cocotb.data_generator import GenerateFrame, BlockType +from xls.modules.zstd.cocotb.memory import init_axi_mem, AxiRamFromFile +from xls.modules.zstd.cocotb.utils import reset, run_test +from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass + +AXI_DATA_W = 64 +AXI_DATA_W_BYTES = AXI_DATA_W // 8 +MAX_ENCODED_FRAME_SIZE_B = 16384 +NOTIFY_CHANNEL = "notify" +OUTPUT_CHANNEL = "output" +RESET_CHANNEL = "reset" + +# Override default widths of AXI response signals +signal_widths = {"bresp": 3} +AxiBBus._signal_widths = signal_widths +AxiBTransaction._signal_widths = signal_widths +AxiBSource._signal_widths = signal_widths +AxiBSink._signal_widths = signal_widths +AxiBMonitor._signal_widths = signal_widths +signal_widths = {"rresp": 3, "rlast": 1} +AxiRBus._signal_widths = signal_widths +AxiRTransaction._signal_widths = signal_widths +AxiRSource._signal_widths = signal_widths +AxiRSink._signal_widths = signal_widths +AxiRMonitor._signal_widths = signal_widths + +@xls_dataclass +class NotifyStruct(XLSStruct): + pass + +@xls_dataclass +class ResetStruct(XLSStruct): + pass + +@xls_dataclass +class OutputStruct(XLSStruct): + data: 64 + length: 32 + last: 1 + +class CSR(Enum): + """ + Maps the offsets to the ZSTD Decoder registers + """ + Status = 0 + Start = 1 + Reset = 2 + InputBuffer = 3 + OutputBuffer = 4 + +class Status(Enum): + """ + Codes for the Status register + """ + IDLE = 0x0 + RUNNING = 0x1 + +def set_termination_event(monitor, event, transactions): + def terminate_cb(_): + if monitor.stats.received_transactions == transactions: + event.set() + monitor.add_callback(terminate_cb) + +def connect_axi_read_bus(dut, name=""): + AXI_AR = "axi_ar" + AXI_R = "axi_r" + + if name != "": + name += "_" + + bus_axi_ar = AxiARBus.from_prefix(dut, name + AXI_AR) + bus_axi_r = AxiRBus.from_prefix(dut, name + AXI_R) + + return AxiReadBus(bus_axi_ar, bus_axi_r) + +def connect_axi_write_bus(dut, name=""): + AXI_AW = "axi_aw" + AXI_W = "axi_w" + AXI_B = "axi_b" + + if name != "": + name += "_" + + bus_axi_aw = AxiAWBus.from_prefix(dut, name + AXI_AW) + bus_axi_w = AxiWBus.from_prefix(dut, name + AXI_W) + bus_axi_b = AxiBBus.from_prefix(dut, name + AXI_B) + + return AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) + +def connect_axi_bus(dut, name=""): + bus_axi_read = connect_axi_read_bus(dut, name) + bus_axi_write = connect_axi_write_bus(dut, name) + + return AxiBus(bus_axi_write, bus_axi_read) + +def get_decoded_frame_bytes(ifh): + dctx = zstandard.ZstdDecompressor() + return dctx.decompress(ifh.read()) + +def get_decoded_frame_buffer(ifh, address, memory=SparseMemory(size=MAX_ENCODED_FRAME_SIZE_B)): + dctx = zstandard.ZstdDecompressor() + memory.write(address, dctx.decompress(ifh.read())) + return memory + +async def csr_write(cpu, csr, data): + if type(data) is int: + data = data.to_bytes(AXI_DATA_W_BYTES, byteorder='little') + assert len(data) <= AXI_DATA_W_BYTES + await cpu.write(csr.value * AXI_DATA_W_BYTES, data) + +async def csr_read(cpu, csr): + return await cpu.read(csr.value * AXI_DATA_W_BYTES, AXI_DATA_W_BYTES) + +async def test_csr(dut): + + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + await reset_dut(dut, 50) + + csr_bus = connect_axi_bus(dut, "csr") + + cpu = AxiMaster(csr_bus, dut.clk, dut.rst) + + await ClockCycles(dut.clk, 10) + i = 0 + for reg in CSR: + # Reset CSR tested in a separate test case + if (reg == CSR.Reset): + continue + expected_src = bytearray.fromhex("0DF0AD8BEFBEADDE") + assert len(expected_src) >= AXI_DATA_W_BYTES + expected = expected_src[-AXI_DATA_W_BYTES:] + expected[0] += i + await csr_write(cpu, reg, expected) + read = await csr_read(cpu, reg) + assert read.data == expected, "Expected data doesn't match contents of the {}".format(reg) + i += 1 + await ClockCycles(dut.clk, 10) + +async def test_reset(dut): + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + await reset_dut(dut, 50) + + (reset_channel, reset_monitor) = connect_xls_channel(dut, RESET_CHANNEL, ResetStruct) + + csr_bus = connect_axi_bus(dut, "csr") + cpu = AxiMaster(csr_bus, dut.clk, dut.rst) + + scoreboard = Scoreboard(dut) + + rst_struct = ResetStruct() + # Expect single reset signal on reset output channel + expected_reset = [rst_struct] + scoreboard.add_interface(reset_monitor, expected_reset) + + await ClockCycles(dut.clk, 10) + await start_decoder(cpu) + timeout = 10 + status = await csr_read(cpu, CSR.Status) + while ((int.from_bytes(status.data, byteorder='little') == Status.IDLE.value) & (timeout != 0)): + status = await csr_read(cpu, CSR.Status) + timeout -= 1 + assert (timeout != 0) + + await csr_write(cpu, CSR.Reset, 0x1) + await wait_for_idle(cpu, 10) + + await ClockCycles(dut.clk, 10) + +async def configure_decoder(cpu, ibuf_addr, obuf_addr): + status = await csr_read(cpu, CSR.Status) + if int.from_bytes(status.data, byteorder='little') != Status.IDLE.value: + await csr_write(cpu, CSR.Reset, 0x1) + await csr_write(cpu, CSR.InputBuffer, ibuf_addr) + await csr_write(cpu, CSR.OutputBuffer, obuf_addr) + +async def start_decoder(cpu): + await csr_write(cpu, CSR.Start, 0x1) + +async def wait_for_idle(cpu, timeout=100): + status = await csr_read(cpu, CSR.Status) + while ((int.from_bytes(status.data, byteorder='little') != Status.IDLE.value) & (timeout != 0)): + status = await csr_read(cpu, CSR.Status) + timeout -= 1 + assert (timeout != 0) + +def generate_expected_output(decoded_frame): + packets = [] + frame_len = len(decoded_frame) + last_len = frame_len % 8 + for i in range(frame_len // 8): + start_id = i * 8 + end_id = start_id + 8 + packet_data = int.from_bytes(decoded_frame[start_id:end_id], byteorder='little') + last_packet = (end_id==frame_len) + packet = OutputStruct(data=packet_data, length=64, last=last_packet) + packets.append(packet) + if (last_len): + packet_data = int.from_bytes(decoded_frame[-last_len:], byteorder='little') + packet = OutputStruct(data=packet_data, length=last_len*8, last=True) + packets.append(packet) + return packets + +async def reset_dut(dut, rst_len=10): + dut.rst.setimmediatevalue(0) + await ClockCycles(dut.clk, rst_len) + dut.rst.setimmediatevalue(1) + await ClockCycles(dut.clk, rst_len) + dut.rst.setimmediatevalue(0) + +def connect_xls_channel(dut, channel_name, xls_struct): + channel = XLSChannel(dut, channel_name, dut.clk, start_now=True) + monitor = XLSChannelMonitor(dut, channel_name, dut.clk, xls_struct) + + return (channel, monitor) + +def prepare_test_environment(dut): + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + scoreboard = Scoreboard(dut) + + memory_bus = connect_axi_bus(dut, "memory") + csr_bus = connect_axi_bus(dut, "csr") + axi_buses = { + "memory": memory_bus, + "csr": csr_bus + } + + notify = connect_xls_channel(dut, NOTIFY_CHANNEL, NotifyStruct) + output = connect_xls_channel(dut, OUTPUT_CHANNEL, OutputStruct) + xls_channels = { + "notify": notify, + "output": output + } + + cpu = AxiMaster(csr_bus, dut.clk, dut.rst) + + return (scoreboard, axi_buses, xls_channels, cpu) + +async def test_decoder(dut, seed, block_type, scoreboard, axi_buses, xls_channels, cpu): + memory_bus = axi_buses["memory"] + csr_bus = axi_buses["csr"] + (notify_channel, notify_monitor) = xls_channels[NOTIFY_CHANNEL] + (output_channel, output_monitor) = xls_channels[OUTPUT_CHANNEL] + + assert_notify = Event() + set_termination_event(notify_monitor, assert_notify, 1) + + mem_size = MAX_ENCODED_FRAME_SIZE_B + ibuf_addr = 0x0 + obuf_addr = mem_size // 2 + + #FIXME: use delete_on_close=False after moving to python 3.12 + with tempfile.NamedTemporaryFile(delete=False) as encoded: + await reset_dut(dut, 50) + + # Generate ZSTD frame to temporary file + GenerateFrame(seed, block_type, encoded.name) + + expected_decoded_frame = get_decoded_frame_bytes(encoded) + encoded.close() + expected_output_packets = generate_expected_output(expected_decoded_frame) + + assert_expected_output = Event() + set_termination_event(output_monitor, assert_expected_output, len(expected_output_packets)) + # Monitor stream output for packets with the decoded ZSTD frame + scoreboard.add_interface(output_monitor, expected_output_packets) + + # Initialise testbench memory with generated ZSTD frame + memory = AxiRamFromFile(bus=memory_bus, clock=dut.clk, reset=dut.rst, path=encoded.name, size=mem_size) + + await configure_decoder(cpu, ibuf_addr, obuf_addr) + await start_decoder(cpu) + await assert_expected_output.wait() + await wait_for_idle(cpu) + # TODO: Check decoded frame in memory under `obuf_addr` when ZstdDecoder + # will fully support memory output interface + + await assert_notify.wait() + await ClockCycles(dut.clk, 20) + +@cocotb.test(timeout_time=50, timeout_unit="ms") +async def zstd_csr_test(dut): + await test_csr(dut) + +@cocotb.test(timeout_time=50, timeout_unit="ms") +async def zstd_reset_test(dut): + await test_reset(dut) + +#FIXME: Rework testbench to decode multiple ZSTD frames in one test +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_raw_frames_test_1(dut): + block_type = BlockType.RAW + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 1, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_raw_frames_test_2(dut): + block_type = BlockType.RAW + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 2, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_raw_frames_test_3(dut): + block_type = BlockType.RAW + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 3, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_raw_frames_test_4(dut): + block_type = BlockType.RAW + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 4, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_raw_frames_test_5(dut): + block_type = BlockType.RAW + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 5, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_rle_frames_test_1(dut): + block_type = BlockType.RLE + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 1, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_rle_frames_test_2(dut): + block_type = BlockType.RLE + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 2, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_rle_frames_test_3(dut): + block_type = BlockType.RLE + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 3, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_rle_frames_test_4(dut): + block_type = BlockType.RLE + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 4, block_type, scoreboard, axi_buses, xls_channels, cpu) + +@cocotb.test(timeout_time=20000, timeout_unit="ms") +async def zstd_rle_frames_test_5(dut): + block_type = BlockType.RLE + (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 5, block_type, scoreboard, axi_buses, xls_channels, cpu) + +#@cocotb.test(timeout_time=20000, timeout_unit="ms") +#async def zstd_compressed_frames_test(dut): +# test_cases = 1 +# block_type = BlockType.COMPRESSED +# await test_decoder(dut, test_cases, block_type) +# +#@cocotb.test(timeout_time=20000, timeout_unit="ms") +#async def zstd_random_frames_test(dut): +# test_cases = 1 +# block_type = BlockType.RANDOM +# await test_decoder(dut, test_cases, block_type) + +if __name__ == "__main__": + toplevel = "zstd_dec_wrapper" + verilog_sources = [ + "xls/modules/zstd/zstd_dec.v", + "xls/modules/zstd/rtl/xls_fifo_wrapper.sv", + "xls/modules/zstd/rtl/zstd_dec_wrapper.sv", + "xls/modules/zstd/axi_interconnect_wrapper.v", + "xls/modules/zstd/axi_interconnect.v", + "xls/modules/zstd/arbiter.v", + "xls/modules/zstd/priority_encoder.v", + ] + test_module=[Path(__file__).stem] + run_test(toplevel, test_module, verilog_sources) From 5b89e4c2d39e3166ddf2b1a3db73b19f39ce7c42 Mon Sep 17 00:00:00 2001 From: Krzysztof Oblonczek Date: Tue, 13 May 2025 14:34:53 +0200 Subject: [PATCH 08/30] Use frame generator in tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Robert Winkler Signed-off-by: Robert Winkler Signed-off-by: Krzysztof Obłonczek --- xls/modules/zstd/BUILD | 23 +++ xls/modules/zstd/cocotb/data_generator.py | 19 ++- xls/modules/zstd/zstd_dec_cocotb_test.py | 15 +- xls/modules/zstd/zstd_frame_dslx.py | 170 ++++++++++++++++++++++ 4 files changed, 212 insertions(+), 15 deletions(-) create mode 100644 xls/modules/zstd/zstd_frame_dslx.py diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 420569a42b..7e7dd781ca 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -1446,6 +1446,29 @@ xls_dslx_test( ], ) +py_binary( + name = "zstd_test_frames_generator", + srcs = ["zstd_frame_dslx.py"], + imports = ["."], + main = "zstd_frame_dslx.py", + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("zstandard"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:data_generator", + "@com_google_protobuf//:protobuf_python", + ], +) + +genrule( + name = "zstd_test_frames_generate", + srcs = [], + outs = ["zstd_frame_testcases.x"], + cmd = "$(location :zstd_test_frames_generator) --seed 36 -n 1 --btype COMPRESSED -o $@", + tools = [":zstd_test_frames_generator"], +) + zstd_dec_deps = [ ":axi_csr_accessor_dslx", ":block_header_dec_dslx", diff --git a/xls/modules/zstd/cocotb/data_generator.py b/xls/modules/zstd/cocotb/data_generator.py index 105a9a7ec7..72b60c5eee 100644 --- a/xls/modules/zstd/cocotb/data_generator.py +++ b/xls/modules/zstd/cocotb/data_generator.py @@ -17,6 +17,7 @@ from xls.common import runfiles import subprocess +import zstandard class BlockType(Enum): RAW = 0 @@ -24,6 +25,16 @@ class BlockType(Enum): COMPRESSED = 2 RANDOM = 3 + def __str__(self): + return self.name + + @staticmethod + def from_string(s): + try: + return BlockType[s] + except KeyError as e: + raise ValueError(str(e)) + def CallDecodecorpus(args): decodecorpus = Path(runfiles.get_path("decodecorpus", repository = "zstd")) cmd = args @@ -31,6 +42,10 @@ def CallDecodecorpus(args): cmd_concat = " ".join(cmd) subprocess.run(cmd_concat, shell=True, check=True) +def DecompressFrame(data): + dctx = zstandard.ZstdDecompressor() + return dctx.decompress(data) + def GenerateFrame(seed, btype, output_path): args = [] args.append("-s" + str(seed)) @@ -39,8 +54,8 @@ def GenerateFrame(seed, btype, output_path): args.append("--content-size") # Test payloads up to 16KB args.append("--max-content-size-log=14") - args.append("-p" + output_path); - args.append("-vvvvvvv"); + args.append("-p" + output_path) + args.append("-vvvvvvv") CallDecodecorpus(args) diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index ff9fd5afff..b696272811 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -29,15 +29,13 @@ from cocotbext.axi.axi_ram import AxiRam from cocotbext.axi.sparse_memory import SparseMemory -import zstandard - from xls.common import runfiles from xls.modules.zstd.cocotb.channel import ( XLSChannel, XLSChannelDriver, XLSChannelMonitor, ) -from xls.modules.zstd.cocotb.data_generator import GenerateFrame, BlockType +from xls.modules.zstd.cocotb.data_generator import GenerateFrame, DecompressFrame, BlockType from xls.modules.zstd.cocotb.memory import init_axi_mem, AxiRamFromFile from xls.modules.zstd.cocotb.utils import reset, run_test from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass @@ -132,15 +130,6 @@ def connect_axi_bus(dut, name=""): return AxiBus(bus_axi_write, bus_axi_read) -def get_decoded_frame_bytes(ifh): - dctx = zstandard.ZstdDecompressor() - return dctx.decompress(ifh.read()) - -def get_decoded_frame_buffer(ifh, address, memory=SparseMemory(size=MAX_ENCODED_FRAME_SIZE_B)): - dctx = zstandard.ZstdDecompressor() - memory.write(address, dctx.decompress(ifh.read())) - return memory - async def csr_write(cpu, csr, data): if type(data) is int: data = data.to_bytes(AXI_DATA_W_BYTES, byteorder='little') @@ -300,7 +289,7 @@ async def test_decoder(dut, seed, block_type, scoreboard, axi_buses, xls_channel # Generate ZSTD frame to temporary file GenerateFrame(seed, block_type, encoded.name) - expected_decoded_frame = get_decoded_frame_bytes(encoded) + expected_decoded_frame = DecompressFrame(encoded.read()) encoded.close() expected_output_packets = generate_expected_output(expected_decoded_frame) diff --git a/xls/modules/zstd/zstd_frame_dslx.py b/xls/modules/zstd/zstd_frame_dslx.py new file mode 100644 index 0000000000..65c5573677 --- /dev/null +++ b/xls/modules/zstd/zstd_frame_dslx.py @@ -0,0 +1,170 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import argparse +import math +import random +import tempfile +from pathlib import Path + +from xls.modules.zstd.cocotb.data_generator import ( + BlockType, + DecompressFrame, + GenerateFrame, +) + + +def GenerateTestData(seed, btype): + with tempfile.NamedTemporaryFile() as tmp: + GenerateFrame(seed, btype, tmp.name) + tmp.seek(0) + return tmp.read() + + +def Bytes2DSLX(frames, bytes_per_word, array_name): + frames_hex = [] + maxlen = max(len(frame) for frame in frames) + maxlen_size = math.ceil(maxlen / bytes_per_word) + bits_per_word = bytes_per_word * 8 + for i, frame in enumerate(frames): + frame_hex = [] + for i in range(0, len(frame), bytes_per_word): + # reverse byte order to make them little endian + word = bytes(reversed(frame[i : i + bytes_per_word])).hex() + frame_hex.append(f"uN[{bits_per_word}]:0x{word}") + + array_length = len(frame_hex) + if len(frame) < maxlen: + frame_hex += [f"uN[{bits_per_word}]:0x0", "..."] + + frame_array = ( + f"DataArray<{bits_per_word}, {maxlen_size}>{{\n" + f" length: u32:{len(frame)},\n" + f" array_length: u32:{array_length},\n" + f" data: uN[{bits_per_word}][{maxlen_size}]:[{', '.join(frame_hex)}]\n" + f"}}" + ) + frames_hex.append(frame_array) + + frames_str = ",\n".join(frames_hex) + frames_array = ( + f"pub const {array_name}:DataArray<\n" + f" u32:{bits_per_word},\n" + f" u32:{maxlen_size}\n" + f">[{len(frames_hex)}] = [{frames_str}];\n" + ) + return frames_array + + +def GenerateDataStruct(): + return ( + f"pub struct DataArray{{\n" + f" data: uN[BITS_PER_WORD][LENGTH],\n" + f" length: u32,\n" + f" array_length: u32\n" + f"}}\n" + ) + +def main2(): + parser = argparse.ArgumentParser() + parser.add_argument( + "input", + help="Filename of the decodecorpus input", + type=Path, + ) + parser.add_argument( + "output", + help="Filename of the DSLX output file", + type=Path, + ) + parser.add_argument( + "--bytes-per-word", + help="Width of a word in memory, in bytes", + type=int, + default=8, + ) + + args = parser.parse_args() + + with open(args.input, "rb") as fd: + byte_frames = [fd.read()] + + with open(args.output, "w") as dslx_output: + dslx_output.write(GenerateDataStruct()) + + dslx_frames = Bytes2DSLX(byte_frames, args.bytes_per_word, "FRAMES") + dslx_output.write(dslx_frames) + + byte_frames_decompressed = list(map(DecompressFrame, byte_frames)) + dslx_frames_decompressed = Bytes2DSLX( + byte_frames_decompressed, args.bytes_per_word, "DECOMPRESSED_FRAMES" + ) + dslx_output.write(dslx_frames_decompressed) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "-n", help="Number of testcases to generate", type=int, default=1 + ) + parser.add_argument( + "--seed", help="Seed for the testcases generator", type=int, default=0 + ) + parser.add_argument( + "--btype", + help=( + "Block types allowed in the generated testcases. If multiple block types " + "are supplied, generated testcases will cycle through them" + ), + type=BlockType.from_string, + choices=list(BlockType), + default=BlockType.RANDOM, + nargs="+", + ) + parser.add_argument( + "-o", + "--output", + help="Filename of the DSLX output file", + type=Path, + default=Path("frames_test_data.x"), + ) + parser.add_argument( + "--bytes-per-word", + help="Width of a word in memory, in bytes", + type=int, + default=8, + ) + args = parser.parse_args() + + seed = random.seed(args.seed) + byte_frames = [ + GenerateTestData(random.randrange(2**32), args.btype[i % len(args.btype)]) + for i in range(args.n) + ] + with open(args.output, "w") as dslx_output: + dslx_output.write(GenerateDataStruct()) + + dslx_frames = Bytes2DSLX(byte_frames, args.bytes_per_word, "FRAMES") + dslx_output.write(dslx_frames) + + byte_frames_decompressed = list(map(DecompressFrame, byte_frames)) + dslx_frames_decompressed = Bytes2DSLX( + byte_frames_decompressed, args.bytes_per_word, "DECOMPRESSED_FRAMES" + ) + dslx_output.write(dslx_frames_decompressed) + + +if __name__ == "__main__": + main() From 613a2920bf878ec0ee1765a79cd1450fe00c8068 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Tue, 13 May 2025 14:47:31 +0200 Subject: [PATCH 09/30] modules/zstd/zstd_dec: Write decoded data to the memory ZstdDecoder: * Cocotb tests: * Move third-party verilog modules (AXI Interconnect) to external directory * Replace AXI Interconnect with AXI Crossbar that handles simultaneous AXI Read and Write transactions * Add reference memory and fill it with expected data for comparison against testbench memory at the end of the decoding Internal-tag: [#67272] Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/BUILD | 35 - xls/modules/zstd/axi_interconnect.v | 988 ------------------ xls/modules/zstd/external/BUILD | 33 + xls/modules/zstd/{ => external}/arbiter.v | 0 xls/modules/zstd/external/axi_crossbar.v | 391 +++++++ xls/modules/zstd/external/axi_crossbar_addr.v | 418 ++++++++ xls/modules/zstd/external/axi_crossbar_rd.v | 569 ++++++++++ xls/modules/zstd/external/axi_crossbar_wr.v | 678 ++++++++++++ .../axi_crossbar_wrapper.v} | 200 +++- xls/modules/zstd/external/axi_register_rd.v | 530 ++++++++++ xls/modules/zstd/external/axi_register_wr.v | 691 ++++++++++++ .../zstd/{ => external}/priority_encoder.v | 0 xls/modules/zstd/zstd_dec_cocotb_test.py | 51 +- 13 files changed, 3511 insertions(+), 1073 deletions(-) delete mode 100644 xls/modules/zstd/axi_interconnect.v create mode 100644 xls/modules/zstd/external/BUILD rename xls/modules/zstd/{ => external}/arbiter.v (100%) create mode 100644 xls/modules/zstd/external/axi_crossbar.v create mode 100644 xls/modules/zstd/external/axi_crossbar_addr.v create mode 100644 xls/modules/zstd/external/axi_crossbar_rd.v create mode 100644 xls/modules/zstd/external/axi_crossbar_wr.v rename xls/modules/zstd/{axi_interconnect_wrapper.v => external/axi_crossbar_wrapper.v} (70%) create mode 100644 xls/modules/zstd/external/axi_register_rd.v create mode 100644 xls/modules/zstd/external/axi_register_wr.v rename xls/modules/zstd/{ => external}/priority_encoder.v (100%) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 7e7dd781ca..91a48dd761 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -3724,38 +3724,3 @@ xls_dslx_test( name = "refilling_shift_buffer_mux_dslx_test", library = ":refilling_shift_buffer_mux_dslx", ) - -py_test( - name = "zstd_dec_cocotb_test", - srcs = ["zstd_dec_cocotb_test.py"], - data = [ - ":arbiter.v", - ":axi_interconnect.v", - ":axi_interconnect_wrapper.v", - ":priority_encoder.v", - ":xls_fifo_wrapper.sv", - ":zstd_dec.v", - ":zstd_dec_wrapper.sv", - "@com_icarus_iverilog//:iverilog", - "@com_icarus_iverilog//:vvp", - ], - env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, - imports = ["."], - tags = ["manual"], - visibility = ["//xls:xls_users"], - deps = [ - requirement("cocotb"), - requirement("cocotbext-axi"), - requirement("pytest"), - requirement("zstandard"), - "//xls/common:runfiles", - "//xls/modules/zstd/cocotb:channel", - "//xls/modules/zstd/cocotb:data_generator", - "//xls/modules/zstd/cocotb:memory", - "//xls/modules/zstd/cocotb:utils", - "//xls/modules/zstd/cocotb:xlsstruct", - "@com_google_absl_py//absl:app", - "@com_google_absl_py//absl/flags", - "@com_google_protobuf//:protobuf_python", - ], -) diff --git a/xls/modules/zstd/axi_interconnect.v b/xls/modules/zstd/axi_interconnect.v deleted file mode 100644 index 14256ad7de..0000000000 --- a/xls/modules/zstd/axi_interconnect.v +++ /dev/null @@ -1,988 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 interconnect - */ -module axi_interconnect # -( - // Number of AXI inputs (slave interfaces) - parameter S_COUNT = 4, - // Number of AXI outputs (master interfaces) - parameter M_COUNT = 4, - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Width of ID signal - parameter ID_WIDTH = 8, - // Propagate awuser signal - parameter AWUSER_ENABLE = 0, - // Width of awuser signal - parameter AWUSER_WIDTH = 1, - // Propagate wuser signal - parameter WUSER_ENABLE = 0, - // Width of wuser signal - parameter WUSER_WIDTH = 1, - // Propagate buser signal - parameter BUSER_ENABLE = 0, - // Width of buser signal - parameter BUSER_WIDTH = 1, - // Propagate aruser signal - parameter ARUSER_ENABLE = 0, - // Width of aruser signal - parameter ARUSER_WIDTH = 1, - // Propagate ruser signal - parameter RUSER_ENABLE = 0, - // Width of ruser signal - parameter RUSER_WIDTH = 1, - // Propagate ID field - parameter FORWARD_ID = 0, - // Number of regions per master interface - parameter M_REGIONS = 1, - // Master interface base addresses - // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits - // set to zero for default addressing based on M_ADDR_WIDTH - parameter M_BASE_ADDR = 0, - // Master interface address widths - // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits - parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, - // Read connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}}, - // Write connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}}, - // Secure master (fail operations based on awprot/arprot) - // M_COUNT bits - parameter M_SECURE = {M_COUNT{1'b0}} -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interfaces - */ - input wire [S_COUNT*ID_WIDTH-1:0] s_axi_awid, - input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr, - input wire [S_COUNT*8-1:0] s_axi_awlen, - input wire [S_COUNT*3-1:0] s_axi_awsize, - input wire [S_COUNT*2-1:0] s_axi_awburst, - input wire [S_COUNT-1:0] s_axi_awlock, - input wire [S_COUNT*4-1:0] s_axi_awcache, - input wire [S_COUNT*3-1:0] s_axi_awprot, - input wire [S_COUNT*4-1:0] s_axi_awqos, - input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser, - input wire [S_COUNT-1:0] s_axi_awvalid, - output wire [S_COUNT-1:0] s_axi_awready, - input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata, - input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb, - input wire [S_COUNT-1:0] s_axi_wlast, - input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser, - input wire [S_COUNT-1:0] s_axi_wvalid, - output wire [S_COUNT-1:0] s_axi_wready, - output wire [S_COUNT*ID_WIDTH-1:0] s_axi_bid, - output wire [S_COUNT*2-1:0] s_axi_bresp, - output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser, - output wire [S_COUNT-1:0] s_axi_bvalid, - input wire [S_COUNT-1:0] s_axi_bready, - input wire [S_COUNT*ID_WIDTH-1:0] s_axi_arid, - input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr, - input wire [S_COUNT*8-1:0] s_axi_arlen, - input wire [S_COUNT*3-1:0] s_axi_arsize, - input wire [S_COUNT*2-1:0] s_axi_arburst, - input wire [S_COUNT-1:0] s_axi_arlock, - input wire [S_COUNT*4-1:0] s_axi_arcache, - input wire [S_COUNT*3-1:0] s_axi_arprot, - input wire [S_COUNT*4-1:0] s_axi_arqos, - input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser, - input wire [S_COUNT-1:0] s_axi_arvalid, - output wire [S_COUNT-1:0] s_axi_arready, - output wire [S_COUNT*ID_WIDTH-1:0] s_axi_rid, - output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata, - output wire [S_COUNT*2-1:0] s_axi_rresp, - output wire [S_COUNT-1:0] s_axi_rlast, - output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser, - output wire [S_COUNT-1:0] s_axi_rvalid, - input wire [S_COUNT-1:0] s_axi_rready, - - /* - * AXI master interfaces - */ - output wire [M_COUNT*ID_WIDTH-1:0] m_axi_awid, - output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr, - output wire [M_COUNT*8-1:0] m_axi_awlen, - output wire [M_COUNT*3-1:0] m_axi_awsize, - output wire [M_COUNT*2-1:0] m_axi_awburst, - output wire [M_COUNT-1:0] m_axi_awlock, - output wire [M_COUNT*4-1:0] m_axi_awcache, - output wire [M_COUNT*3-1:0] m_axi_awprot, - output wire [M_COUNT*4-1:0] m_axi_awqos, - output wire [M_COUNT*4-1:0] m_axi_awregion, - output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser, - output wire [M_COUNT-1:0] m_axi_awvalid, - input wire [M_COUNT-1:0] m_axi_awready, - output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata, - output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb, - output wire [M_COUNT-1:0] m_axi_wlast, - output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser, - output wire [M_COUNT-1:0] m_axi_wvalid, - input wire [M_COUNT-1:0] m_axi_wready, - input wire [M_COUNT*ID_WIDTH-1:0] m_axi_bid, - input wire [M_COUNT*2-1:0] m_axi_bresp, - input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser, - input wire [M_COUNT-1:0] m_axi_bvalid, - output wire [M_COUNT-1:0] m_axi_bready, - output wire [M_COUNT*ID_WIDTH-1:0] m_axi_arid, - output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr, - output wire [M_COUNT*8-1:0] m_axi_arlen, - output wire [M_COUNT*3-1:0] m_axi_arsize, - output wire [M_COUNT*2-1:0] m_axi_arburst, - output wire [M_COUNT-1:0] m_axi_arlock, - output wire [M_COUNT*4-1:0] m_axi_arcache, - output wire [M_COUNT*3-1:0] m_axi_arprot, - output wire [M_COUNT*4-1:0] m_axi_arqos, - output wire [M_COUNT*4-1:0] m_axi_arregion, - output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser, - output wire [M_COUNT-1:0] m_axi_arvalid, - input wire [M_COUNT-1:0] m_axi_arready, - input wire [M_COUNT*ID_WIDTH-1:0] m_axi_rid, - input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata, - input wire [M_COUNT*2-1:0] m_axi_rresp, - input wire [M_COUNT-1:0] m_axi_rlast, - input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser, - input wire [M_COUNT-1:0] m_axi_rvalid, - output wire [M_COUNT-1:0] m_axi_rready -); - -parameter CL_S_COUNT = $clog2(S_COUNT); -parameter CL_M_COUNT = $clog2(M_COUNT); - -parameter AUSER_WIDTH = AWUSER_WIDTH > ARUSER_WIDTH ? AWUSER_WIDTH : ARUSER_WIDTH; - -// default address computation -function [M_COUNT*M_REGIONS*ADDR_WIDTH-1:0] calcBaseAddrs(input [31:0] dummy); - integer i; - reg [ADDR_WIDTH-1:0] base; - reg [ADDR_WIDTH-1:0] width; - reg [ADDR_WIDTH-1:0] size; - reg [ADDR_WIDTH-1:0] mask; - begin - calcBaseAddrs = {M_COUNT*M_REGIONS*ADDR_WIDTH{1'b0}}; - base = 0; - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - width = M_ADDR_WIDTH[i*32 +: 32]; - mask = {ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - width); - size = mask + 1; - if (width > 0) begin - if ((base & mask) != 0) begin - base = base + size - (base & mask); // align - end - calcBaseAddrs[i * ADDR_WIDTH +: ADDR_WIDTH] = base; - base = base + size; // increment - end - end - end -endfunction - -parameter M_BASE_ADDR_INT = M_BASE_ADDR ? M_BASE_ADDR : calcBaseAddrs(0); - -integer i, j; - -// check configuration -initial begin - if (M_REGIONS < 1 || M_REGIONS > 16) begin - $error("Error: M_REGIONS must be between 1 and 16 (instance %m)"); - $finish; - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin - $error("Error: address width out of range (instance %m)"); - $finish; - end - end - - $display("Addressing configuration for axi_interconnect instance %m"); - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32]) begin - $display("%2d (%2d): %x / %02d -- %x-%x", - i/M_REGIONS, i%M_REGIONS, - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[i*32 +: 32], - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) - ); - end - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if ((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & (2**M_ADDR_WIDTH[i*32 +: 32]-1)) != 0) begin - $display("Region not aligned:"); - $display("%2d (%2d): %x / %2d -- %x-%x", - i/M_REGIONS, i%M_REGIONS, - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[i*32 +: 32], - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) - ); - $error("Error: address range not aligned (instance %m)"); - $finish; - end - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - for (j = i+1; j < M_COUNT*M_REGIONS; j = j + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32] && M_ADDR_WIDTH[j*32 +: 32]) begin - if (((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])))) - && ((M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin - $display("Overlapping regions:"); - $display("%2d (%2d): %x / %2d -- %x-%x", - i/M_REGIONS, i%M_REGIONS, - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[i*32 +: 32], - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) - ); - $display("%2d (%2d): %x / %2d -- %x-%x", - j/M_REGIONS, j%M_REGIONS, - M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[j*32 +: 32], - M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]), - M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])) - ); - $error("Error: address ranges overlap (instance %m)"); - $finish; - end - end - end - end -end - -localparam [2:0] - STATE_IDLE = 3'd0, - STATE_DECODE = 3'd1, - STATE_WRITE = 3'd2, - STATE_WRITE_RESP = 3'd3, - STATE_WRITE_DROP = 3'd4, - STATE_READ = 3'd5, - STATE_READ_DROP = 3'd6, - STATE_WAIT_IDLE = 3'd7; - -reg [2:0] state_reg = STATE_IDLE, state_next; - -reg match; - -reg [CL_M_COUNT-1:0] m_select_reg = 2'd0, m_select_next; -reg [ID_WIDTH-1:0] axi_id_reg = {ID_WIDTH{1'b0}}, axi_id_next; -reg [ADDR_WIDTH-1:0] axi_addr_reg = {ADDR_WIDTH{1'b0}}, axi_addr_next; -reg axi_addr_valid_reg = 1'b0, axi_addr_valid_next; -reg [7:0] axi_len_reg = 8'd0, axi_len_next; -reg [2:0] axi_size_reg = 3'd0, axi_size_next; -reg [1:0] axi_burst_reg = 2'd0, axi_burst_next; -reg axi_lock_reg = 1'b0, axi_lock_next; -reg [3:0] axi_cache_reg = 4'd0, axi_cache_next; -reg [2:0] axi_prot_reg = 3'b000, axi_prot_next; -reg [3:0] axi_qos_reg = 4'd0, axi_qos_next; -reg [3:0] axi_region_reg = 4'd0, axi_region_next; -reg [AUSER_WIDTH-1:0] axi_auser_reg = {AUSER_WIDTH{1'b0}}, axi_auser_next; -reg [1:0] axi_bresp_reg = 2'b00, axi_bresp_next; -reg [BUSER_WIDTH-1:0] axi_buser_reg = {BUSER_WIDTH{1'b0}}, axi_buser_next; - -reg [S_COUNT-1:0] s_axi_awready_reg = 0, s_axi_awready_next; -reg [S_COUNT-1:0] s_axi_wready_reg = 0, s_axi_wready_next; -reg [S_COUNT-1:0] s_axi_bvalid_reg = 0, s_axi_bvalid_next; -reg [S_COUNT-1:0] s_axi_arready_reg = 0, s_axi_arready_next; - -reg [M_COUNT-1:0] m_axi_awvalid_reg = 0, m_axi_awvalid_next; -reg [M_COUNT-1:0] m_axi_bready_reg = 0, m_axi_bready_next; -reg [M_COUNT-1:0] m_axi_arvalid_reg = 0, m_axi_arvalid_next; -reg [M_COUNT-1:0] m_axi_rready_reg = 0, m_axi_rready_next; - -// internal datapath -reg [ID_WIDTH-1:0] s_axi_rid_int; -reg [DATA_WIDTH-1:0] s_axi_rdata_int; -reg [1:0] s_axi_rresp_int; -reg s_axi_rlast_int; -reg [RUSER_WIDTH-1:0] s_axi_ruser_int; -reg s_axi_rvalid_int; -reg s_axi_rready_int_reg = 1'b0; -wire s_axi_rready_int_early; - -reg [DATA_WIDTH-1:0] m_axi_wdata_int; -reg [STRB_WIDTH-1:0] m_axi_wstrb_int; -reg m_axi_wlast_int; -reg [WUSER_WIDTH-1:0] m_axi_wuser_int; -reg m_axi_wvalid_int; -reg m_axi_wready_int_reg = 1'b0; -wire m_axi_wready_int_early; - -assign s_axi_awready = s_axi_awready_reg; -assign s_axi_wready = s_axi_wready_reg; -assign s_axi_bid = {S_COUNT{axi_id_reg}}; -assign s_axi_bresp = {S_COUNT{axi_bresp_reg}}; -assign s_axi_buser = {S_COUNT{BUSER_ENABLE ? axi_buser_reg : {BUSER_WIDTH{1'b0}}}}; -assign s_axi_bvalid = s_axi_bvalid_reg; -assign s_axi_arready = s_axi_arready_reg; - -assign m_axi_awid = {M_COUNT{FORWARD_ID ? axi_id_reg : {ID_WIDTH{1'b0}}}}; -assign m_axi_awaddr = {M_COUNT{axi_addr_reg}}; -assign m_axi_awlen = {M_COUNT{axi_len_reg}}; -assign m_axi_awsize = {M_COUNT{axi_size_reg}}; -assign m_axi_awburst = {M_COUNT{axi_burst_reg}}; -assign m_axi_awlock = {M_COUNT{axi_lock_reg}}; -assign m_axi_awcache = {M_COUNT{axi_cache_reg}}; -assign m_axi_awprot = {M_COUNT{axi_prot_reg}}; -assign m_axi_awqos = {M_COUNT{axi_qos_reg}}; -assign m_axi_awregion = {M_COUNT{axi_region_reg}}; -assign m_axi_awuser = {M_COUNT{AWUSER_ENABLE ? axi_auser_reg[AWUSER_WIDTH-1:0] : {AWUSER_WIDTH{1'b0}}}}; -assign m_axi_awvalid = m_axi_awvalid_reg; -assign m_axi_bready = m_axi_bready_reg; -assign m_axi_arid = {M_COUNT{FORWARD_ID ? axi_id_reg : {ID_WIDTH{1'b0}}}}; -assign m_axi_araddr = {M_COUNT{axi_addr_reg}}; -assign m_axi_arlen = {M_COUNT{axi_len_reg}}; -assign m_axi_arsize = {M_COUNT{axi_size_reg}}; -assign m_axi_arburst = {M_COUNT{axi_burst_reg}}; -assign m_axi_arlock = {M_COUNT{axi_lock_reg}}; -assign m_axi_arcache = {M_COUNT{axi_cache_reg}}; -assign m_axi_arprot = {M_COUNT{axi_prot_reg}}; -assign m_axi_arqos = {M_COUNT{axi_qos_reg}}; -assign m_axi_arregion = {M_COUNT{axi_region_reg}}; -assign m_axi_aruser = {M_COUNT{ARUSER_ENABLE ? axi_auser_reg[ARUSER_WIDTH-1:0] : {ARUSER_WIDTH{1'b0}}}}; -assign m_axi_arvalid = m_axi_arvalid_reg; -assign m_axi_rready = m_axi_rready_reg; - -// slave side mux -wire [(CL_S_COUNT > 0 ? CL_S_COUNT-1 : 0):0] s_select; - -wire [ID_WIDTH-1:0] current_s_axi_awid = s_axi_awid[s_select*ID_WIDTH +: ID_WIDTH]; -wire [ADDR_WIDTH-1:0] current_s_axi_awaddr = s_axi_awaddr[s_select*ADDR_WIDTH +: ADDR_WIDTH]; -wire [7:0] current_s_axi_awlen = s_axi_awlen[s_select*8 +: 8]; -wire [2:0] current_s_axi_awsize = s_axi_awsize[s_select*3 +: 3]; -wire [1:0] current_s_axi_awburst = s_axi_awburst[s_select*2 +: 2]; -wire current_s_axi_awlock = s_axi_awlock[s_select]; -wire [3:0] current_s_axi_awcache = s_axi_awcache[s_select*4 +: 4]; -wire [2:0] current_s_axi_awprot = s_axi_awprot[s_select*3 +: 3]; -wire [3:0] current_s_axi_awqos = s_axi_awqos[s_select*4 +: 4]; -wire [AWUSER_WIDTH-1:0] current_s_axi_awuser = s_axi_awuser[s_select*AWUSER_WIDTH +: AWUSER_WIDTH]; -wire current_s_axi_awvalid = s_axi_awvalid[s_select]; -wire current_s_axi_awready = s_axi_awready[s_select]; -wire [DATA_WIDTH-1:0] current_s_axi_wdata = s_axi_wdata[s_select*DATA_WIDTH +: DATA_WIDTH]; -wire [STRB_WIDTH-1:0] current_s_axi_wstrb = s_axi_wstrb[s_select*STRB_WIDTH +: STRB_WIDTH]; -wire current_s_axi_wlast = s_axi_wlast[s_select]; -wire [WUSER_WIDTH-1:0] current_s_axi_wuser = s_axi_wuser[s_select*WUSER_WIDTH +: WUSER_WIDTH]; -wire current_s_axi_wvalid = s_axi_wvalid[s_select]; -wire current_s_axi_wready = s_axi_wready[s_select]; -wire [ID_WIDTH-1:0] current_s_axi_bid = s_axi_bid[s_select*ID_WIDTH +: ID_WIDTH]; -wire [1:0] current_s_axi_bresp = s_axi_bresp[s_select*2 +: 2]; -wire [BUSER_WIDTH-1:0] current_s_axi_buser = s_axi_buser[s_select*BUSER_WIDTH +: BUSER_WIDTH]; -wire current_s_axi_bvalid = s_axi_bvalid[s_select]; -wire current_s_axi_bready = s_axi_bready[s_select]; -wire [ID_WIDTH-1:0] current_s_axi_arid = s_axi_arid[s_select*ID_WIDTH +: ID_WIDTH]; -wire [ADDR_WIDTH-1:0] current_s_axi_araddr = s_axi_araddr[s_select*ADDR_WIDTH +: ADDR_WIDTH]; -wire [7:0] current_s_axi_arlen = s_axi_arlen[s_select*8 +: 8]; -wire [2:0] current_s_axi_arsize = s_axi_arsize[s_select*3 +: 3]; -wire [1:0] current_s_axi_arburst = s_axi_arburst[s_select*2 +: 2]; -wire current_s_axi_arlock = s_axi_arlock[s_select]; -wire [3:0] current_s_axi_arcache = s_axi_arcache[s_select*4 +: 4]; -wire [2:0] current_s_axi_arprot = s_axi_arprot[s_select*3 +: 3]; -wire [3:0] current_s_axi_arqos = s_axi_arqos[s_select*4 +: 4]; -wire [ARUSER_WIDTH-1:0] current_s_axi_aruser = s_axi_aruser[s_select*ARUSER_WIDTH +: ARUSER_WIDTH]; -wire current_s_axi_arvalid = s_axi_arvalid[s_select]; -wire current_s_axi_arready = s_axi_arready[s_select]; -wire [ID_WIDTH-1:0] current_s_axi_rid = s_axi_rid[s_select*ID_WIDTH +: ID_WIDTH]; -wire [DATA_WIDTH-1:0] current_s_axi_rdata = s_axi_rdata[s_select*DATA_WIDTH +: DATA_WIDTH]; -wire [1:0] current_s_axi_rresp = s_axi_rresp[s_select*2 +: 2]; -wire current_s_axi_rlast = s_axi_rlast[s_select]; -wire [RUSER_WIDTH-1:0] current_s_axi_ruser = s_axi_ruser[s_select*RUSER_WIDTH +: RUSER_WIDTH]; -wire current_s_axi_rvalid = s_axi_rvalid[s_select]; -wire current_s_axi_rready = s_axi_rready[s_select]; - -// master side mux -wire [ID_WIDTH-1:0] current_m_axi_awid = m_axi_awid[m_select_reg*ID_WIDTH +: ID_WIDTH]; -wire [ADDR_WIDTH-1:0] current_m_axi_awaddr = m_axi_awaddr[m_select_reg*ADDR_WIDTH +: ADDR_WIDTH]; -wire [7:0] current_m_axi_awlen = m_axi_awlen[m_select_reg*8 +: 8]; -wire [2:0] current_m_axi_awsize = m_axi_awsize[m_select_reg*3 +: 3]; -wire [1:0] current_m_axi_awburst = m_axi_awburst[m_select_reg*2 +: 2]; -wire current_m_axi_awlock = m_axi_awlock[m_select_reg]; -wire [3:0] current_m_axi_awcache = m_axi_awcache[m_select_reg*4 +: 4]; -wire [2:0] current_m_axi_awprot = m_axi_awprot[m_select_reg*3 +: 3]; -wire [3:0] current_m_axi_awqos = m_axi_awqos[m_select_reg*4 +: 4]; -wire [3:0] current_m_axi_awregion = m_axi_awregion[m_select_reg*4 +: 4]; -wire [AWUSER_WIDTH-1:0] current_m_axi_awuser = m_axi_awuser[m_select_reg*AWUSER_WIDTH +: AWUSER_WIDTH]; -wire current_m_axi_awvalid = m_axi_awvalid[m_select_reg]; -wire current_m_axi_awready = m_axi_awready[m_select_reg]; -wire [DATA_WIDTH-1:0] current_m_axi_wdata = m_axi_wdata[m_select_reg*DATA_WIDTH +: DATA_WIDTH]; -wire [STRB_WIDTH-1:0] current_m_axi_wstrb = m_axi_wstrb[m_select_reg*STRB_WIDTH +: STRB_WIDTH]; -wire current_m_axi_wlast = m_axi_wlast[m_select_reg]; -wire [WUSER_WIDTH-1:0] current_m_axi_wuser = m_axi_wuser[m_select_reg*WUSER_WIDTH +: WUSER_WIDTH]; -wire current_m_axi_wvalid = m_axi_wvalid[m_select_reg]; -wire current_m_axi_wready = m_axi_wready[m_select_reg]; -wire [ID_WIDTH-1:0] current_m_axi_bid = m_axi_bid[m_select_reg*ID_WIDTH +: ID_WIDTH]; -wire [1:0] current_m_axi_bresp = m_axi_bresp[m_select_reg*2 +: 2]; -wire [BUSER_WIDTH-1:0] current_m_axi_buser = m_axi_buser[m_select_reg*BUSER_WIDTH +: BUSER_WIDTH]; -wire current_m_axi_bvalid = m_axi_bvalid[m_select_reg]; -wire current_m_axi_bready = m_axi_bready[m_select_reg]; -wire [ID_WIDTH-1:0] current_m_axi_arid = m_axi_arid[m_select_reg*ID_WIDTH +: ID_WIDTH]; -wire [ADDR_WIDTH-1:0] current_m_axi_araddr = m_axi_araddr[m_select_reg*ADDR_WIDTH +: ADDR_WIDTH]; -wire [7:0] current_m_axi_arlen = m_axi_arlen[m_select_reg*8 +: 8]; -wire [2:0] current_m_axi_arsize = m_axi_arsize[m_select_reg*3 +: 3]; -wire [1:0] current_m_axi_arburst = m_axi_arburst[m_select_reg*2 +: 2]; -wire current_m_axi_arlock = m_axi_arlock[m_select_reg]; -wire [3:0] current_m_axi_arcache = m_axi_arcache[m_select_reg*4 +: 4]; -wire [2:0] current_m_axi_arprot = m_axi_arprot[m_select_reg*3 +: 3]; -wire [3:0] current_m_axi_arqos = m_axi_arqos[m_select_reg*4 +: 4]; -wire [3:0] current_m_axi_arregion = m_axi_arregion[m_select_reg*4 +: 4]; -wire [ARUSER_WIDTH-1:0] current_m_axi_aruser = m_axi_aruser[m_select_reg*ARUSER_WIDTH +: ARUSER_WIDTH]; -wire current_m_axi_arvalid = m_axi_arvalid[m_select_reg]; -wire current_m_axi_arready = m_axi_arready[m_select_reg]; -wire [ID_WIDTH-1:0] current_m_axi_rid = m_axi_rid[m_select_reg*ID_WIDTH +: ID_WIDTH]; -wire [DATA_WIDTH-1:0] current_m_axi_rdata = m_axi_rdata[m_select_reg*DATA_WIDTH +: DATA_WIDTH]; -wire [1:0] current_m_axi_rresp = m_axi_rresp[m_select_reg*2 +: 2]; -wire current_m_axi_rlast = m_axi_rlast[m_select_reg]; -wire [RUSER_WIDTH-1:0] current_m_axi_ruser = m_axi_ruser[m_select_reg*RUSER_WIDTH +: RUSER_WIDTH]; -wire current_m_axi_rvalid = m_axi_rvalid[m_select_reg]; -wire current_m_axi_rready = m_axi_rready[m_select_reg]; - -// arbiter instance -wire [S_COUNT*2-1:0] request; -wire [S_COUNT*2-1:0] acknowledge; -wire [S_COUNT*2-1:0] grant; -wire grant_valid; -wire [CL_S_COUNT:0] grant_encoded; - -wire read = grant_encoded[0]; -assign s_select = grant_encoded >> 1; - -arbiter #( - .PORTS(S_COUNT*2), - .ARB_TYPE_ROUND_ROBIN(1), - .ARB_BLOCK(1), - .ARB_BLOCK_ACK(1), - .ARB_LSB_HIGH_PRIORITY(1) -) -arb_inst ( - .clk(clk), - .rst(rst), - .request(request), - .acknowledge(acknowledge), - .grant(grant), - .grant_valid(grant_valid), - .grant_encoded(grant_encoded) -); - -genvar n; - -// request generation -generate -for (n = 0; n < S_COUNT; n = n + 1) begin - assign request[2*n] = s_axi_awvalid[n]; - assign request[2*n+1] = s_axi_arvalid[n]; -end -endgenerate - -// acknowledge generation -generate -for (n = 0; n < S_COUNT; n = n + 1) begin - assign acknowledge[2*n] = grant[2*n] && s_axi_bvalid[n] && s_axi_bready[n]; - assign acknowledge[2*n+1] = grant[2*n+1] && s_axi_rvalid[n] && s_axi_rready[n] && s_axi_rlast[n]; -end -endgenerate - -always @* begin - state_next = STATE_IDLE; - - match = 1'b0; - - m_select_next = m_select_reg; - axi_id_next = axi_id_reg; - axi_addr_next = axi_addr_reg; - axi_addr_valid_next = axi_addr_valid_reg; - axi_len_next = axi_len_reg; - axi_size_next = axi_size_reg; - axi_burst_next = axi_burst_reg; - axi_lock_next = axi_lock_reg; - axi_cache_next = axi_cache_reg; - axi_prot_next = axi_prot_reg; - axi_qos_next = axi_qos_reg; - axi_region_next = axi_region_reg; - axi_auser_next = axi_auser_reg; - axi_bresp_next = axi_bresp_reg; - axi_buser_next = axi_buser_reg; - - s_axi_awready_next = 0; - s_axi_wready_next = 0; - s_axi_bvalid_next = s_axi_bvalid_reg & ~s_axi_bready; - s_axi_arready_next = 0; - - m_axi_awvalid_next = m_axi_awvalid_reg & ~m_axi_awready; - m_axi_bready_next = 0; - m_axi_arvalid_next = m_axi_arvalid_reg & ~m_axi_arready; - m_axi_rready_next = 0; - - s_axi_rid_int = axi_id_reg; - s_axi_rdata_int = current_m_axi_rdata; - s_axi_rresp_int = current_m_axi_rresp; - s_axi_rlast_int = current_m_axi_rlast; - s_axi_ruser_int = current_m_axi_ruser; - s_axi_rvalid_int = 1'b0; - - m_axi_wdata_int = current_s_axi_wdata; - m_axi_wstrb_int = current_s_axi_wstrb; - m_axi_wlast_int = current_s_axi_wlast; - m_axi_wuser_int = current_s_axi_wuser; - m_axi_wvalid_int = 1'b0; - - case (state_reg) - STATE_IDLE: begin - // idle state; wait for arbitration - - if (grant_valid) begin - - axi_addr_valid_next = 1'b1; - - if (read) begin - // reading - axi_addr_next = current_s_axi_araddr; - axi_prot_next = current_s_axi_arprot; - axi_id_next = current_s_axi_arid; - axi_addr_next = current_s_axi_araddr; - axi_len_next = current_s_axi_arlen; - axi_size_next = current_s_axi_arsize; - axi_burst_next = current_s_axi_arburst; - axi_lock_next = current_s_axi_arlock; - axi_cache_next = current_s_axi_arcache; - axi_prot_next = current_s_axi_arprot; - axi_qos_next = current_s_axi_arqos; - axi_auser_next = current_s_axi_aruser; - s_axi_arready_next[s_select] = 1'b1; - end else begin - // writing - axi_addr_next = current_s_axi_awaddr; - axi_prot_next = current_s_axi_awprot; - axi_id_next = current_s_axi_awid; - axi_addr_next = current_s_axi_awaddr; - axi_len_next = current_s_axi_awlen; - axi_size_next = current_s_axi_awsize; - axi_burst_next = current_s_axi_awburst; - axi_lock_next = current_s_axi_awlock; - axi_cache_next = current_s_axi_awcache; - axi_prot_next = current_s_axi_awprot; - axi_qos_next = current_s_axi_awqos; - axi_auser_next = current_s_axi_awuser; - s_axi_awready_next[s_select] = 1'b1; - end - - state_next = STATE_DECODE; - end else begin - state_next = STATE_IDLE; - end - end - STATE_DECODE: begin - // decode state; determine master interface - - match = 1'b0; - for (i = 0; i < M_COUNT; i = i + 1) begin - for (j = 0; j < M_REGIONS; j = j + 1) begin - if (M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32] && (!M_SECURE[i] || !axi_prot_reg[1]) && ((read ? M_CONNECT_READ : M_CONNECT_WRITE) & (1 << (s_select+i*S_COUNT))) && (axi_addr_reg >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32]) == (M_BASE_ADDR_INT[(i*M_REGIONS+j)*ADDR_WIDTH +: ADDR_WIDTH] >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32])) begin - m_select_next = i; - axi_region_next = j; - match = 1'b1; - end - end - end - - if (match) begin - if (read) begin - // reading - m_axi_rready_next[m_select_reg] = s_axi_rready_int_early; - state_next = STATE_READ; - end else begin - // writing - s_axi_wready_next[s_select] = m_axi_wready_int_early; - state_next = STATE_WRITE; - end - end else begin - // no match; return decode error - if (read) begin - // reading - state_next = STATE_READ_DROP; - end else begin - // writing - axi_bresp_next = 2'b11; - s_axi_wready_next[s_select] = 1'b1; - state_next = STATE_WRITE_DROP; - end - end - end - STATE_WRITE: begin - // write state; store and forward write data - s_axi_wready_next[s_select] = m_axi_wready_int_early; - - if (axi_addr_valid_reg) begin - m_axi_awvalid_next[m_select_reg] = 1'b1; - end - axi_addr_valid_next = 1'b0; - - if (current_s_axi_wready && current_s_axi_wvalid) begin - m_axi_wdata_int = current_s_axi_wdata; - m_axi_wstrb_int = current_s_axi_wstrb; - m_axi_wlast_int = current_s_axi_wlast; - m_axi_wuser_int = current_s_axi_wuser; - m_axi_wvalid_int = 1'b1; - - if (current_s_axi_wlast) begin - s_axi_wready_next[s_select] = 1'b0; - m_axi_bready_next[m_select_reg] = 1'b1; - state_next = STATE_WRITE_RESP; - end else begin - state_next = STATE_WRITE; - end - end else begin - state_next = STATE_WRITE; - end - end - STATE_WRITE_RESP: begin - // write response state; store and forward write response - m_axi_bready_next[m_select_reg] = 1'b1; - - if (current_m_axi_bready && current_m_axi_bvalid) begin - m_axi_bready_next[m_select_reg] = 1'b0; - axi_bresp_next = current_m_axi_bresp; - s_axi_bvalid_next[s_select] = 1'b1; - state_next = STATE_WAIT_IDLE; - end else begin - state_next = STATE_WRITE_RESP; - end - end - STATE_WRITE_DROP: begin - // write drop state; drop write data - s_axi_wready_next[s_select] = 1'b1; - - axi_addr_valid_next = 1'b0; - - if (current_s_axi_wready && current_s_axi_wvalid && current_s_axi_wlast) begin - s_axi_wready_next[s_select] = 1'b0; - s_axi_bvalid_next[s_select] = 1'b1; - state_next = STATE_WAIT_IDLE; - end else begin - state_next = STATE_WRITE_DROP; - end - end - STATE_READ: begin - // read state; store and forward read response - m_axi_rready_next[m_select_reg] = s_axi_rready_int_early; - - if (axi_addr_valid_reg) begin - m_axi_arvalid_next[m_select_reg] = 1'b1; - end - axi_addr_valid_next = 1'b0; - - if (current_m_axi_rready && current_m_axi_rvalid) begin - s_axi_rid_int = axi_id_reg; - s_axi_rdata_int = current_m_axi_rdata; - s_axi_rresp_int = current_m_axi_rresp; - s_axi_rlast_int = current_m_axi_rlast; - s_axi_ruser_int = current_m_axi_ruser; - s_axi_rvalid_int = 1'b1; - - if (current_m_axi_rlast) begin - m_axi_rready_next[m_select_reg] = 1'b0; - state_next = STATE_WAIT_IDLE; - end else begin - state_next = STATE_READ; - end - end else begin - state_next = STATE_READ; - end - end - STATE_READ_DROP: begin - // read drop state; generate decode error read response - - s_axi_rid_int = axi_id_reg; - s_axi_rdata_int = {DATA_WIDTH{1'b0}}; - s_axi_rresp_int = 2'b11; - s_axi_rlast_int = axi_len_reg == 0; - s_axi_ruser_int = {RUSER_WIDTH{1'b0}}; - s_axi_rvalid_int = 1'b1; - - if (s_axi_rready_int_reg) begin - axi_len_next = axi_len_reg - 1; - if (axi_len_reg == 0) begin - state_next = STATE_WAIT_IDLE; - end else begin - state_next = STATE_READ_DROP; - end - end else begin - state_next = STATE_READ_DROP; - end - end - STATE_WAIT_IDLE: begin - // wait for idle state; wait untl grant valid is deasserted - - if (!grant_valid || acknowledge) begin - state_next = STATE_IDLE; - end else begin - state_next = STATE_WAIT_IDLE; - end - end - endcase -end - -always @(posedge clk) begin - if (rst) begin - state_reg <= STATE_IDLE; - - s_axi_awready_reg <= 0; - s_axi_wready_reg <= 0; - s_axi_bvalid_reg <= 0; - s_axi_arready_reg <= 0; - - m_axi_awvalid_reg <= 0; - m_axi_bready_reg <= 0; - m_axi_arvalid_reg <= 0; - m_axi_rready_reg <= 0; - end else begin - state_reg <= state_next; - - s_axi_awready_reg <= s_axi_awready_next; - s_axi_wready_reg <= s_axi_wready_next; - s_axi_bvalid_reg <= s_axi_bvalid_next; - s_axi_arready_reg <= s_axi_arready_next; - - m_axi_awvalid_reg <= m_axi_awvalid_next; - m_axi_bready_reg <= m_axi_bready_next; - m_axi_arvalid_reg <= m_axi_arvalid_next; - m_axi_rready_reg <= m_axi_rready_next; - end - - m_select_reg <= m_select_next; - axi_id_reg <= axi_id_next; - axi_addr_reg <= axi_addr_next; - axi_addr_valid_reg <= axi_addr_valid_next; - axi_len_reg <= axi_len_next; - axi_size_reg <= axi_size_next; - axi_burst_reg <= axi_burst_next; - axi_lock_reg <= axi_lock_next; - axi_cache_reg <= axi_cache_next; - axi_prot_reg <= axi_prot_next; - axi_qos_reg <= axi_qos_next; - axi_region_reg <= axi_region_next; - axi_auser_reg <= axi_auser_next; - axi_bresp_reg <= axi_bresp_next; - axi_buser_reg <= axi_buser_next; -end - -// output datapath logic (R channel) -reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; -reg [1:0] s_axi_rresp_reg = 2'd0; -reg s_axi_rlast_reg = 1'b0; -reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = 1'b0; -reg [S_COUNT-1:0] s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next; - -reg [ID_WIDTH-1:0] temp_s_axi_rid_reg = {ID_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] temp_s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; -reg [1:0] temp_s_axi_rresp_reg = 2'd0; -reg temp_s_axi_rlast_reg = 1'b0; -reg [RUSER_WIDTH-1:0] temp_s_axi_ruser_reg = 1'b0; -reg temp_s_axi_rvalid_reg = 1'b0, temp_s_axi_rvalid_next; - -// datapath control -reg store_axi_r_int_to_output; -reg store_axi_r_int_to_temp; -reg store_axi_r_temp_to_output; - -assign s_axi_rid = {S_COUNT{s_axi_rid_reg}}; -assign s_axi_rdata = {S_COUNT{s_axi_rdata_reg}}; -assign s_axi_rresp = {S_COUNT{s_axi_rresp_reg}}; -assign s_axi_rlast = {S_COUNT{s_axi_rlast_reg}}; -assign s_axi_ruser = {S_COUNT{RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}}}}; -assign s_axi_rvalid = s_axi_rvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign s_axi_rready_int_early = current_s_axi_rready | (~temp_s_axi_rvalid_reg & (~current_s_axi_rvalid | ~s_axi_rvalid_int)); - -always @* begin - // transfer sink ready state to source - s_axi_rvalid_next = s_axi_rvalid_reg; - temp_s_axi_rvalid_next = temp_s_axi_rvalid_reg; - - store_axi_r_int_to_output = 1'b0; - store_axi_r_int_to_temp = 1'b0; - store_axi_r_temp_to_output = 1'b0; - - if (s_axi_rready_int_reg) begin - // input is ready - if (current_s_axi_rready | ~current_s_axi_rvalid) begin - // output is ready or currently not valid, transfer data to output - s_axi_rvalid_next[s_select] = s_axi_rvalid_int; - store_axi_r_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_s_axi_rvalid_next = s_axi_rvalid_int; - store_axi_r_int_to_temp = 1'b1; - end - end else if (current_s_axi_rready) begin - // input is not ready, but output is ready - s_axi_rvalid_next[s_select] = temp_s_axi_rvalid_reg; - temp_s_axi_rvalid_next = 1'b0; - store_axi_r_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_rvalid_reg <= 1'b0; - s_axi_rready_int_reg <= 1'b0; - temp_s_axi_rvalid_reg <= 1'b0; - end else begin - s_axi_rvalid_reg <= s_axi_rvalid_next; - s_axi_rready_int_reg <= s_axi_rready_int_early; - temp_s_axi_rvalid_reg <= temp_s_axi_rvalid_next; - end - - // datapath - if (store_axi_r_int_to_output) begin - s_axi_rid_reg <= s_axi_rid_int; - s_axi_rdata_reg <= s_axi_rdata_int; - s_axi_rresp_reg <= s_axi_rresp_int; - s_axi_rlast_reg <= s_axi_rlast_int; - s_axi_ruser_reg <= s_axi_ruser_int; - end else if (store_axi_r_temp_to_output) begin - s_axi_rid_reg <= temp_s_axi_rid_reg; - s_axi_rdata_reg <= temp_s_axi_rdata_reg; - s_axi_rresp_reg <= temp_s_axi_rresp_reg; - s_axi_rlast_reg <= temp_s_axi_rlast_reg; - s_axi_ruser_reg <= temp_s_axi_ruser_reg; - end - - if (store_axi_r_int_to_temp) begin - temp_s_axi_rid_reg <= s_axi_rid_int; - temp_s_axi_rdata_reg <= s_axi_rdata_int; - temp_s_axi_rresp_reg <= s_axi_rresp_int; - temp_s_axi_rlast_reg <= s_axi_rlast_int; - temp_s_axi_ruser_reg <= s_axi_ruser_int; - end -end - -// output datapath logic (W channel) -reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; -reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; -reg m_axi_wlast_reg = 1'b0; -reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = 1'b0; -reg [M_COUNT-1:0] m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next; - -reg [DATA_WIDTH-1:0] temp_m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; -reg [STRB_WIDTH-1:0] temp_m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; -reg temp_m_axi_wlast_reg = 1'b0; -reg [WUSER_WIDTH-1:0] temp_m_axi_wuser_reg = 1'b0; -reg temp_m_axi_wvalid_reg = 1'b0, temp_m_axi_wvalid_next; - -// datapath control -reg store_axi_w_int_to_output; -reg store_axi_w_int_to_temp; -reg store_axi_w_temp_to_output; - -assign m_axi_wdata = {M_COUNT{m_axi_wdata_reg}}; -assign m_axi_wstrb = {M_COUNT{m_axi_wstrb_reg}}; -assign m_axi_wlast = {M_COUNT{m_axi_wlast_reg}}; -assign m_axi_wuser = {M_COUNT{WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}}}}; -assign m_axi_wvalid = m_axi_wvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign m_axi_wready_int_early = current_m_axi_wready | (~temp_m_axi_wvalid_reg & (~current_m_axi_wvalid | ~m_axi_wvalid_int)); - -always @* begin - // transfer sink ready state to source - m_axi_wvalid_next = m_axi_wvalid_reg; - temp_m_axi_wvalid_next = temp_m_axi_wvalid_reg; - - store_axi_w_int_to_output = 1'b0; - store_axi_w_int_to_temp = 1'b0; - store_axi_w_temp_to_output = 1'b0; - - if (m_axi_wready_int_reg) begin - // input is ready - if (current_m_axi_wready | ~current_m_axi_wvalid) begin - // output is ready or currently not valid, transfer data to output - m_axi_wvalid_next[m_select_reg] = m_axi_wvalid_int; - store_axi_w_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axi_wvalid_next = m_axi_wvalid_int; - store_axi_w_int_to_temp = 1'b1; - end - end else if (current_m_axi_wready) begin - // input is not ready, but output is ready - m_axi_wvalid_next[m_select_reg] = temp_m_axi_wvalid_reg; - temp_m_axi_wvalid_next = 1'b0; - store_axi_w_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - m_axi_wvalid_reg <= 1'b0; - m_axi_wready_int_reg <= 1'b0; - temp_m_axi_wvalid_reg <= 1'b0; - end else begin - m_axi_wvalid_reg <= m_axi_wvalid_next; - m_axi_wready_int_reg <= m_axi_wready_int_early; - temp_m_axi_wvalid_reg <= temp_m_axi_wvalid_next; - end - - // datapath - if (store_axi_w_int_to_output) begin - m_axi_wdata_reg <= m_axi_wdata_int; - m_axi_wstrb_reg <= m_axi_wstrb_int; - m_axi_wlast_reg <= m_axi_wlast_int; - m_axi_wuser_reg <= m_axi_wuser_int; - end else if (store_axi_w_temp_to_output) begin - m_axi_wdata_reg <= temp_m_axi_wdata_reg; - m_axi_wstrb_reg <= temp_m_axi_wstrb_reg; - m_axi_wlast_reg <= temp_m_axi_wlast_reg; - m_axi_wuser_reg <= temp_m_axi_wuser_reg; - end - - if (store_axi_w_int_to_temp) begin - temp_m_axi_wdata_reg <= m_axi_wdata_int; - temp_m_axi_wstrb_reg <= m_axi_wstrb_int; - temp_m_axi_wlast_reg <= m_axi_wlast_int; - temp_m_axi_wuser_reg <= m_axi_wuser_int; - end -end - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/BUILD b/xls/modules/zstd/external/BUILD new file mode 100644 index 0000000000..f24cb69fe0 --- /dev/null +++ b/xls/modules/zstd/external/BUILD @@ -0,0 +1,33 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//xls:xls_users"], + licenses = ["notice"], +) + +exports_files( + [ + "arbiter.v", + "axi_crossbar.v", + "axi_crossbar_addr.v", + "axi_crossbar_rd.v", + "axi_crossbar_wr.v", + "axi_crossbar_wrapper.v", + "axi_register_rd.v", + "axi_register_wr.v", + "priority_encoder.v", + ], +) diff --git a/xls/modules/zstd/arbiter.v b/xls/modules/zstd/external/arbiter.v similarity index 100% rename from xls/modules/zstd/arbiter.v rename to xls/modules/zstd/external/arbiter.v diff --git a/xls/modules/zstd/external/axi_crossbar.v b/xls/modules/zstd/external/axi_crossbar.v new file mode 100644 index 0000000000..991d45403a --- /dev/null +++ b/xls/modules/zstd/external/axi_crossbar.v @@ -0,0 +1,391 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 crossbar + */ +module axi_crossbar # +( + // Number of AXI inputs (slave interfaces) + parameter S_COUNT = 4, + // Number of AXI outputs (master interfaces) + parameter M_COUNT = 4, + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Input ID field width (from AXI masters) + parameter S_ID_WIDTH = 8, + // Output ID field width (towards AXI slaves) + // Additional bits required for response routing + parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), + // Propagate awuser signal + parameter AWUSER_ENABLE = 0, + // Width of awuser signal + parameter AWUSER_WIDTH = 1, + // Propagate wuser signal + parameter WUSER_ENABLE = 0, + // Width of wuser signal + parameter WUSER_WIDTH = 1, + // Propagate buser signal + parameter BUSER_ENABLE = 0, + // Width of buser signal + parameter BUSER_WIDTH = 1, + // Propagate aruser signal + parameter ARUSER_ENABLE = 0, + // Width of aruser signal + parameter ARUSER_WIDTH = 1, + // Propagate ruser signal + parameter RUSER_ENABLE = 0, + // Width of ruser signal + parameter RUSER_WIDTH = 1, + // Number of concurrent unique IDs for each slave interface + // S_COUNT concatenated fields of 32 bits + parameter S_THREADS = {S_COUNT{32'd2}}, + // Number of concurrent operations for each slave interface + // S_COUNT concatenated fields of 32 bits + parameter S_ACCEPT = {S_COUNT{32'd16}}, + // Number of regions per master interface + parameter M_REGIONS = 1, + // Master interface base addresses + // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits + // set to zero for default addressing based on M_ADDR_WIDTH + parameter M_BASE_ADDR = 0, + // Master interface address widths + // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits + parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, + // Read connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}}, + // Write connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}}, + // Number of concurrent operations for each master interface + // M_COUNT concatenated fields of 32 bits + parameter M_ISSUE = {M_COUNT{32'd4}}, + // Secure master (fail operations based on awprot/arprot) + // M_COUNT bits + parameter M_SECURE = {M_COUNT{1'b0}}, + // Slave interface AW channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_AW_REG_TYPE = {S_COUNT{2'd0}}, + // Slave interface W channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_W_REG_TYPE = {S_COUNT{2'd0}}, + // Slave interface B channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_B_REG_TYPE = {S_COUNT{2'd1}}, + // Slave interface AR channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_AR_REG_TYPE = {S_COUNT{2'd0}}, + // Slave interface R channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_R_REG_TYPE = {S_COUNT{2'd2}}, + // Master interface AW channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_AW_REG_TYPE = {M_COUNT{2'd1}}, + // Master interface W channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_W_REG_TYPE = {M_COUNT{2'd2}}, + // Master interface B channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_B_REG_TYPE = {M_COUNT{2'd0}}, + // Master interface AR channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_AR_REG_TYPE = {M_COUNT{2'd1}}, + // Master interface R channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_R_REG_TYPE = {M_COUNT{2'd0}} +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interfaces + */ + input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr, + input wire [S_COUNT*8-1:0] s_axi_awlen, + input wire [S_COUNT*3-1:0] s_axi_awsize, + input wire [S_COUNT*2-1:0] s_axi_awburst, + input wire [S_COUNT-1:0] s_axi_awlock, + input wire [S_COUNT*4-1:0] s_axi_awcache, + input wire [S_COUNT*3-1:0] s_axi_awprot, + input wire [S_COUNT*4-1:0] s_axi_awqos, + input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser, + input wire [S_COUNT-1:0] s_axi_awvalid, + output wire [S_COUNT-1:0] s_axi_awready, + input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata, + input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb, + input wire [S_COUNT-1:0] s_axi_wlast, + input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser, + input wire [S_COUNT-1:0] s_axi_wvalid, + output wire [S_COUNT-1:0] s_axi_wready, + output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid, + output wire [S_COUNT*2-1:0] s_axi_bresp, + output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser, + output wire [S_COUNT-1:0] s_axi_bvalid, + input wire [S_COUNT-1:0] s_axi_bready, + input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr, + input wire [S_COUNT*8-1:0] s_axi_arlen, + input wire [S_COUNT*3-1:0] s_axi_arsize, + input wire [S_COUNT*2-1:0] s_axi_arburst, + input wire [S_COUNT-1:0] s_axi_arlock, + input wire [S_COUNT*4-1:0] s_axi_arcache, + input wire [S_COUNT*3-1:0] s_axi_arprot, + input wire [S_COUNT*4-1:0] s_axi_arqos, + input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser, + input wire [S_COUNT-1:0] s_axi_arvalid, + output wire [S_COUNT-1:0] s_axi_arready, + output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid, + output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata, + output wire [S_COUNT*2-1:0] s_axi_rresp, + output wire [S_COUNT-1:0] s_axi_rlast, + output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser, + output wire [S_COUNT-1:0] s_axi_rvalid, + input wire [S_COUNT-1:0] s_axi_rready, + + /* + * AXI master interfaces + */ + output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [M_COUNT*8-1:0] m_axi_awlen, + output wire [M_COUNT*3-1:0] m_axi_awsize, + output wire [M_COUNT*2-1:0] m_axi_awburst, + output wire [M_COUNT-1:0] m_axi_awlock, + output wire [M_COUNT*4-1:0] m_axi_awcache, + output wire [M_COUNT*3-1:0] m_axi_awprot, + output wire [M_COUNT*4-1:0] m_axi_awqos, + output wire [M_COUNT*4-1:0] m_axi_awregion, + output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser, + output wire [M_COUNT-1:0] m_axi_awvalid, + input wire [M_COUNT-1:0] m_axi_awready, + output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata, + output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb, + output wire [M_COUNT-1:0] m_axi_wlast, + output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser, + output wire [M_COUNT-1:0] m_axi_wvalid, + input wire [M_COUNT-1:0] m_axi_wready, + input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid, + input wire [M_COUNT*2-1:0] m_axi_bresp, + input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser, + input wire [M_COUNT-1:0] m_axi_bvalid, + output wire [M_COUNT-1:0] m_axi_bready, + output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr, + output wire [M_COUNT*8-1:0] m_axi_arlen, + output wire [M_COUNT*3-1:0] m_axi_arsize, + output wire [M_COUNT*2-1:0] m_axi_arburst, + output wire [M_COUNT-1:0] m_axi_arlock, + output wire [M_COUNT*4-1:0] m_axi_arcache, + output wire [M_COUNT*3-1:0] m_axi_arprot, + output wire [M_COUNT*4-1:0] m_axi_arqos, + output wire [M_COUNT*4-1:0] m_axi_arregion, + output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser, + output wire [M_COUNT-1:0] m_axi_arvalid, + input wire [M_COUNT-1:0] m_axi_arready, + input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid, + input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata, + input wire [M_COUNT*2-1:0] m_axi_rresp, + input wire [M_COUNT-1:0] m_axi_rlast, + input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser, + input wire [M_COUNT-1:0] m_axi_rvalid, + output wire [M_COUNT-1:0] m_axi_rready +); + +axi_crossbar_wr #( + .S_COUNT(S_COUNT), + .M_COUNT(M_COUNT), + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .S_ID_WIDTH(S_ID_WIDTH), + .M_ID_WIDTH(M_ID_WIDTH), + .AWUSER_ENABLE(AWUSER_ENABLE), + .AWUSER_WIDTH(AWUSER_WIDTH), + .WUSER_ENABLE(WUSER_ENABLE), + .WUSER_WIDTH(WUSER_WIDTH), + .BUSER_ENABLE(BUSER_ENABLE), + .BUSER_WIDTH(BUSER_WIDTH), + .S_THREADS(S_THREADS), + .S_ACCEPT(S_ACCEPT), + .M_REGIONS(M_REGIONS), + .M_BASE_ADDR(M_BASE_ADDR), + .M_ADDR_WIDTH(M_ADDR_WIDTH), + .M_CONNECT(M_CONNECT_WRITE), + .M_ISSUE(M_ISSUE), + .M_SECURE(M_SECURE), + .S_AW_REG_TYPE(S_AW_REG_TYPE), + .S_W_REG_TYPE (S_W_REG_TYPE), + .S_B_REG_TYPE (S_B_REG_TYPE) +) +axi_crossbar_wr_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI slave interfaces + */ + .s_axi_awid(s_axi_awid), + .s_axi_awaddr(s_axi_awaddr), + .s_axi_awlen(s_axi_awlen), + .s_axi_awsize(s_axi_awsize), + .s_axi_awburst(s_axi_awburst), + .s_axi_awlock(s_axi_awlock), + .s_axi_awcache(s_axi_awcache), + .s_axi_awprot(s_axi_awprot), + .s_axi_awqos(s_axi_awqos), + .s_axi_awuser(s_axi_awuser), + .s_axi_awvalid(s_axi_awvalid), + .s_axi_awready(s_axi_awready), + .s_axi_wdata(s_axi_wdata), + .s_axi_wstrb(s_axi_wstrb), + .s_axi_wlast(s_axi_wlast), + .s_axi_wuser(s_axi_wuser), + .s_axi_wvalid(s_axi_wvalid), + .s_axi_wready(s_axi_wready), + .s_axi_bid(s_axi_bid), + .s_axi_bresp(s_axi_bresp), + .s_axi_buser(s_axi_buser), + .s_axi_bvalid(s_axi_bvalid), + .s_axi_bready(s_axi_bready), + + /* + * AXI master interfaces + */ + .m_axi_awid(m_axi_awid), + .m_axi_awaddr(m_axi_awaddr), + .m_axi_awlen(m_axi_awlen), + .m_axi_awsize(m_axi_awsize), + .m_axi_awburst(m_axi_awburst), + .m_axi_awlock(m_axi_awlock), + .m_axi_awcache(m_axi_awcache), + .m_axi_awprot(m_axi_awprot), + .m_axi_awqos(m_axi_awqos), + .m_axi_awregion(m_axi_awregion), + .m_axi_awuser(m_axi_awuser), + .m_axi_awvalid(m_axi_awvalid), + .m_axi_awready(m_axi_awready), + .m_axi_wdata(m_axi_wdata), + .m_axi_wstrb(m_axi_wstrb), + .m_axi_wlast(m_axi_wlast), + .m_axi_wuser(m_axi_wuser), + .m_axi_wvalid(m_axi_wvalid), + .m_axi_wready(m_axi_wready), + .m_axi_bid(m_axi_bid), + .m_axi_bresp(m_axi_bresp), + .m_axi_buser(m_axi_buser), + .m_axi_bvalid(m_axi_bvalid), + .m_axi_bready(m_axi_bready) +); + +axi_crossbar_rd #( + .S_COUNT(S_COUNT), + .M_COUNT(M_COUNT), + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .S_ID_WIDTH(S_ID_WIDTH), + .M_ID_WIDTH(M_ID_WIDTH), + .ARUSER_ENABLE(ARUSER_ENABLE), + .ARUSER_WIDTH(ARUSER_WIDTH), + .RUSER_ENABLE(RUSER_ENABLE), + .RUSER_WIDTH(RUSER_WIDTH), + .S_THREADS(S_THREADS), + .S_ACCEPT(S_ACCEPT), + .M_REGIONS(M_REGIONS), + .M_BASE_ADDR(M_BASE_ADDR), + .M_ADDR_WIDTH(M_ADDR_WIDTH), + .M_CONNECT(M_CONNECT_READ), + .M_ISSUE(M_ISSUE), + .M_SECURE(M_SECURE), + .S_AR_REG_TYPE(S_AR_REG_TYPE), + .S_R_REG_TYPE (S_R_REG_TYPE) +) +axi_crossbar_rd_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI slave interfaces + */ + .s_axi_arid(s_axi_arid), + .s_axi_araddr(s_axi_araddr), + .s_axi_arlen(s_axi_arlen), + .s_axi_arsize(s_axi_arsize), + .s_axi_arburst(s_axi_arburst), + .s_axi_arlock(s_axi_arlock), + .s_axi_arcache(s_axi_arcache), + .s_axi_arprot(s_axi_arprot), + .s_axi_arqos(s_axi_arqos), + .s_axi_aruser(s_axi_aruser), + .s_axi_arvalid(s_axi_arvalid), + .s_axi_arready(s_axi_arready), + .s_axi_rid(s_axi_rid), + .s_axi_rdata(s_axi_rdata), + .s_axi_rresp(s_axi_rresp), + .s_axi_rlast(s_axi_rlast), + .s_axi_ruser(s_axi_ruser), + .s_axi_rvalid(s_axi_rvalid), + .s_axi_rready(s_axi_rready), + + /* + * AXI master interfaces + */ + .m_axi_arid(m_axi_arid), + .m_axi_araddr(m_axi_araddr), + .m_axi_arlen(m_axi_arlen), + .m_axi_arsize(m_axi_arsize), + .m_axi_arburst(m_axi_arburst), + .m_axi_arlock(m_axi_arlock), + .m_axi_arcache(m_axi_arcache), + .m_axi_arprot(m_axi_arprot), + .m_axi_arqos(m_axi_arqos), + .m_axi_arregion(m_axi_arregion), + .m_axi_aruser(m_axi_aruser), + .m_axi_arvalid(m_axi_arvalid), + .m_axi_arready(m_axi_arready), + .m_axi_rid(m_axi_rid), + .m_axi_rdata(m_axi_rdata), + .m_axi_rresp(m_axi_rresp), + .m_axi_rlast(m_axi_rlast), + .m_axi_ruser(m_axi_ruser), + .m_axi_rvalid(m_axi_rvalid), + .m_axi_rready(m_axi_rready) +); + +endmodule + +`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_addr.v b/xls/modules/zstd/external/axi_crossbar_addr.v new file mode 100644 index 0000000000..7b7846526b --- /dev/null +++ b/xls/modules/zstd/external/axi_crossbar_addr.v @@ -0,0 +1,418 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 crossbar address decode and admission control + */ +module axi_crossbar_addr # +( + // Slave interface index + parameter S = 0, + // Number of AXI inputs (slave interfaces) + parameter S_COUNT = 4, + // Number of AXI outputs (master interfaces) + parameter M_COUNT = 4, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // ID field width + parameter ID_WIDTH = 8, + // Number of concurrent unique IDs + parameter S_THREADS = 32'd2, + // Number of concurrent operations + parameter S_ACCEPT = 32'd16, + // Number of regions per master interface + parameter M_REGIONS = 1, + // Master interface base addresses + // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits + // set to zero for default addressing based on M_ADDR_WIDTH + parameter M_BASE_ADDR = 0, + // Master interface address widths + // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits + parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, + // Connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}}, + // Secure master (fail operations based on awprot/arprot) + // M_COUNT bits + parameter M_SECURE = {M_COUNT{1'b0}}, + // Enable write command output + parameter WC_OUTPUT = 0 +) +( + input wire clk, + input wire rst, + + /* + * Address input + */ + input wire [ID_WIDTH-1:0] s_axi_aid, + input wire [ADDR_WIDTH-1:0] s_axi_aaddr, + input wire [2:0] s_axi_aprot, + input wire [3:0] s_axi_aqos, + input wire s_axi_avalid, + output wire s_axi_aready, + + /* + * Address output + */ + output wire [3:0] m_axi_aregion, + output wire [$clog2(M_COUNT)-1:0] m_select, + output wire m_axi_avalid, + input wire m_axi_aready, + + /* + * Write command output + */ + output wire [$clog2(M_COUNT)-1:0] m_wc_select, + output wire m_wc_decerr, + output wire m_wc_valid, + input wire m_wc_ready, + + /* + * Reply command output + */ + output wire m_rc_decerr, + output wire m_rc_valid, + input wire m_rc_ready, + + /* + * Completion input + */ + input wire [ID_WIDTH-1:0] s_cpl_id, + input wire s_cpl_valid +); + +parameter CL_S_COUNT = $clog2(S_COUNT); +parameter CL_M_COUNT = $clog2(M_COUNT); + +parameter S_INT_THREADS = S_THREADS > S_ACCEPT ? S_ACCEPT : S_THREADS; +parameter CL_S_INT_THREADS = $clog2(S_INT_THREADS); +parameter CL_S_ACCEPT = $clog2(S_ACCEPT); + +// default address computation +function [M_COUNT*M_REGIONS*ADDR_WIDTH-1:0] calcBaseAddrs(input [31:0] dummy); + integer i; + reg [ADDR_WIDTH-1:0] base; + reg [ADDR_WIDTH-1:0] width; + reg [ADDR_WIDTH-1:0] size; + reg [ADDR_WIDTH-1:0] mask; + begin + calcBaseAddrs = {M_COUNT*M_REGIONS*ADDR_WIDTH{1'b0}}; + base = 0; + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + width = M_ADDR_WIDTH[i*32 +: 32]; + mask = {ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - width); + size = mask + 1; + if (width > 0) begin + if ((base & mask) != 0) begin + base = base + size - (base & mask); // align + end + calcBaseAddrs[i * ADDR_WIDTH +: ADDR_WIDTH] = base; + base = base + size; // increment + end + end + end +endfunction + +parameter M_BASE_ADDR_INT = M_BASE_ADDR ? M_BASE_ADDR : calcBaseAddrs(0); + +integer i, j; + +// check configuration +initial begin + if (S_ACCEPT < 1) begin + $error("Error: need at least 1 accept (instance %m)"); + $finish; + end + + if (S_THREADS < 1) begin + $error("Error: need at least 1 thread (instance %m)"); + $finish; + end + + if (S_THREADS > S_ACCEPT) begin + $warning("Warning: requested thread count larger than accept count; limiting thread count to accept count (instance %m)"); + end + + if (M_REGIONS < 1) begin + $error("Error: need at least 1 region (instance %m)"); + $finish; + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin + $error("Error: address width out of range (instance %m)"); + $finish; + end + end + + $display("Addressing configuration for axi_crossbar_addr instance %m"); + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32]) begin + $display("%2d (%2d): %x / %02d -- %x-%x", + i/M_REGIONS, i%M_REGIONS, + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[i*32 +: 32], + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + ); + end + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if ((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & (2**M_ADDR_WIDTH[i*32 +: 32]-1)) != 0) begin + $display("Region not aligned:"); + $display("%2d (%2d): %x / %2d -- %x-%x", + i/M_REGIONS, i%M_REGIONS, + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[i*32 +: 32], + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + ); + $error("Error: address range not aligned (instance %m)"); + $finish; + end + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + for (j = i+1; j < M_COUNT*M_REGIONS; j = j + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && M_ADDR_WIDTH[j*32 +: 32]) begin + if (((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])))) + && ((M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin + $display("Overlapping regions:"); + $display("%2d (%2d): %x / %2d -- %x-%x", + i/M_REGIONS, i%M_REGIONS, + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[i*32 +: 32], + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + ); + $display("%2d (%2d): %x / %2d -- %x-%x", + j/M_REGIONS, j%M_REGIONS, + M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH], + M_ADDR_WIDTH[j*32 +: 32], + M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]), + M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])) + ); + $error("Error: address ranges overlap (instance %m)"); + $finish; + end + end + end + end +end + +localparam [2:0] + STATE_IDLE = 3'd0, + STATE_DECODE = 3'd1; + +reg [2:0] state_reg = STATE_IDLE, state_next; + +reg s_axi_aready_reg = 0, s_axi_aready_next; + +reg [3:0] m_axi_aregion_reg = 4'd0, m_axi_aregion_next; +reg [CL_M_COUNT-1:0] m_select_reg = 0, m_select_next; +reg m_axi_avalid_reg = 1'b0, m_axi_avalid_next; +reg m_decerr_reg = 1'b0, m_decerr_next; +reg m_wc_valid_reg = 1'b0, m_wc_valid_next; +reg m_rc_valid_reg = 1'b0, m_rc_valid_next; + +assign s_axi_aready = s_axi_aready_reg; + +assign m_axi_aregion = m_axi_aregion_reg; +assign m_select = m_select_reg; +assign m_axi_avalid = m_axi_avalid_reg; + +assign m_wc_select = m_select_reg; +assign m_wc_decerr = m_decerr_reg; +assign m_wc_valid = m_wc_valid_reg; + +assign m_rc_decerr = m_decerr_reg; +assign m_rc_valid = m_rc_valid_reg; + +reg match; +reg trans_start; +reg trans_complete; + +reg [$clog2(S_ACCEPT+1)-1:0] trans_count_reg = 0; +wire trans_limit = trans_count_reg >= S_ACCEPT && !trans_complete; + +// transfer ID thread tracking +reg [ID_WIDTH-1:0] thread_id_reg[S_INT_THREADS-1:0]; +reg [CL_M_COUNT-1:0] thread_m_reg[S_INT_THREADS-1:0]; +reg [3:0] thread_region_reg[S_INT_THREADS-1:0]; +reg [$clog2(S_ACCEPT+1)-1:0] thread_count_reg[S_INT_THREADS-1:0]; + +wire [S_INT_THREADS-1:0] thread_active; +wire [S_INT_THREADS-1:0] thread_match; +wire [S_INT_THREADS-1:0] thread_match_dest; +wire [S_INT_THREADS-1:0] thread_cpl_match; +wire [S_INT_THREADS-1:0] thread_trans_start; +wire [S_INT_THREADS-1:0] thread_trans_complete; + +generate + genvar n; + + for (n = 0; n < S_INT_THREADS; n = n + 1) begin + initial begin + thread_count_reg[n] <= 0; + end + + assign thread_active[n] = thread_count_reg[n] != 0; + assign thread_match[n] = thread_active[n] && thread_id_reg[n] == s_axi_aid; + assign thread_match_dest[n] = thread_match[n] && thread_m_reg[n] == m_select_next && (M_REGIONS < 2 || thread_region_reg[n] == m_axi_aregion_next); + assign thread_cpl_match[n] = thread_active[n] && thread_id_reg[n] == s_cpl_id; + assign thread_trans_start[n] = (thread_match[n] || (!thread_active[n] && !thread_match && !(thread_trans_start & ({S_INT_THREADS{1'b1}} >> (S_INT_THREADS-n))))) && trans_start; + assign thread_trans_complete[n] = thread_cpl_match[n] && trans_complete; + + always @(posedge clk) begin + if (rst) begin + thread_count_reg[n] <= 0; + end else begin + if (thread_trans_start[n] && !thread_trans_complete[n]) begin + thread_count_reg[n] <= thread_count_reg[n] + 1; + end else if (!thread_trans_start[n] && thread_trans_complete[n]) begin + thread_count_reg[n] <= thread_count_reg[n] - 1; + end + end + + if (thread_trans_start[n]) begin + thread_id_reg[n] <= s_axi_aid; + thread_m_reg[n] <= m_select_next; + thread_region_reg[n] <= m_axi_aregion_next; + end + end + end +endgenerate + +always @* begin + state_next = STATE_IDLE; + + match = 1'b0; + trans_start = 1'b0; + trans_complete = 1'b0; + + s_axi_aready_next = 1'b0; + + m_axi_aregion_next = m_axi_aregion_reg; + m_select_next = m_select_reg; + m_axi_avalid_next = m_axi_avalid_reg && !m_axi_aready; + m_decerr_next = m_decerr_reg; + m_wc_valid_next = m_wc_valid_reg && !m_wc_ready; + m_rc_valid_next = m_rc_valid_reg && !m_rc_ready; + + case (state_reg) + STATE_IDLE: begin + // idle state, store values + s_axi_aready_next = 1'b0; + + if (s_axi_avalid && !s_axi_aready) begin + match = 1'b0; + for (i = 0; i < M_COUNT; i = i + 1) begin + for (j = 0; j < M_REGIONS; j = j + 1) begin + if (M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32] && (!M_SECURE[i] || !s_axi_aprot[1]) && (M_CONNECT & (1 << (S+i*S_COUNT))) && (s_axi_aaddr >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32]) == (M_BASE_ADDR_INT[(i*M_REGIONS+j)*ADDR_WIDTH +: ADDR_WIDTH] >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32])) begin + m_select_next = i; + m_axi_aregion_next = j; + match = 1'b1; + end + end + end + + if (match) begin + // address decode successful + if (!trans_limit && (thread_match_dest || (!(&thread_active) && !thread_match))) begin + // transaction limit not reached + m_axi_avalid_next = 1'b1; + m_decerr_next = 1'b0; + m_wc_valid_next = WC_OUTPUT; + m_rc_valid_next = 1'b0; + trans_start = 1'b1; + state_next = STATE_DECODE; + end else begin + // transaction limit reached; block in idle + state_next = STATE_IDLE; + end + end else begin + // decode error + m_axi_avalid_next = 1'b0; + m_decerr_next = 1'b1; + m_wc_valid_next = WC_OUTPUT; + m_rc_valid_next = 1'b1; + state_next = STATE_DECODE; + end + end else begin + state_next = STATE_IDLE; + end + end + STATE_DECODE: begin + if (!m_axi_avalid_next && (!m_wc_valid_next || !WC_OUTPUT) && !m_rc_valid_next) begin + s_axi_aready_next = 1'b1; + state_next = STATE_IDLE; + end else begin + state_next = STATE_DECODE; + end + end + endcase + + // manage completions + trans_complete = s_cpl_valid; +end + +always @(posedge clk) begin + if (rst) begin + state_reg <= STATE_IDLE; + s_axi_aready_reg <= 1'b0; + m_axi_avalid_reg <= 1'b0; + m_wc_valid_reg <= 1'b0; + m_rc_valid_reg <= 1'b0; + + trans_count_reg <= 0; + end else begin + state_reg <= state_next; + s_axi_aready_reg <= s_axi_aready_next; + m_axi_avalid_reg <= m_axi_avalid_next; + m_wc_valid_reg <= m_wc_valid_next; + m_rc_valid_reg <= m_rc_valid_next; + + if (trans_start && !trans_complete) begin + trans_count_reg <= trans_count_reg + 1; + end else if (!trans_start && trans_complete) begin + trans_count_reg <= trans_count_reg - 1; + end + end + + m_axi_aregion_reg <= m_axi_aregion_next; + m_select_reg <= m_select_next; + m_decerr_reg <= m_decerr_next; +end + +endmodule + +`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_rd.v b/xls/modules/zstd/external/axi_crossbar_rd.v new file mode 100644 index 0000000000..2b1410ac62 --- /dev/null +++ b/xls/modules/zstd/external/axi_crossbar_rd.v @@ -0,0 +1,569 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 crossbar (read) + */ +module axi_crossbar_rd # +( + // Number of AXI inputs (slave interfaces) + parameter S_COUNT = 4, + // Number of AXI outputs (master interfaces) + parameter M_COUNT = 4, + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Input ID field width (from AXI masters) + parameter S_ID_WIDTH = 8, + // Output ID field width (towards AXI slaves) + // Additional bits required for response routing + parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), + // Propagate aruser signal + parameter ARUSER_ENABLE = 0, + // Width of aruser signal + parameter ARUSER_WIDTH = 1, + // Propagate ruser signal + parameter RUSER_ENABLE = 0, + // Width of ruser signal + parameter RUSER_WIDTH = 1, + // Number of concurrent unique IDs for each slave interface + // S_COUNT concatenated fields of 32 bits + parameter S_THREADS = {S_COUNT{32'd2}}, + // Number of concurrent operations for each slave interface + // S_COUNT concatenated fields of 32 bits + parameter S_ACCEPT = {S_COUNT{32'd16}}, + // Number of regions per master interface + parameter M_REGIONS = 1, + // Master interface base addresses + // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits + // set to zero for default addressing based on M_ADDR_WIDTH + parameter M_BASE_ADDR = 0, + // Master interface address widths + // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits + parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, + // Read connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}}, + // Number of concurrent operations for each master interface + // M_COUNT concatenated fields of 32 bits + parameter M_ISSUE = {M_COUNT{32'd4}}, + // Secure master (fail operations based on awprot/arprot) + // M_COUNT bits + parameter M_SECURE = {M_COUNT{1'b0}}, + // Slave interface AR channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_AR_REG_TYPE = {S_COUNT{2'd0}}, + // Slave interface R channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_R_REG_TYPE = {S_COUNT{2'd2}}, + // Master interface AR channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_AR_REG_TYPE = {M_COUNT{2'd1}}, + // Master interface R channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_R_REG_TYPE = {M_COUNT{2'd0}} +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interfaces + */ + input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr, + input wire [S_COUNT*8-1:0] s_axi_arlen, + input wire [S_COUNT*3-1:0] s_axi_arsize, + input wire [S_COUNT*2-1:0] s_axi_arburst, + input wire [S_COUNT-1:0] s_axi_arlock, + input wire [S_COUNT*4-1:0] s_axi_arcache, + input wire [S_COUNT*3-1:0] s_axi_arprot, + input wire [S_COUNT*4-1:0] s_axi_arqos, + input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser, + input wire [S_COUNT-1:0] s_axi_arvalid, + output wire [S_COUNT-1:0] s_axi_arready, + output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid, + output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata, + output wire [S_COUNT*2-1:0] s_axi_rresp, + output wire [S_COUNT-1:0] s_axi_rlast, + output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser, + output wire [S_COUNT-1:0] s_axi_rvalid, + input wire [S_COUNT-1:0] s_axi_rready, + + /* + * AXI master interfaces + */ + output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr, + output wire [M_COUNT*8-1:0] m_axi_arlen, + output wire [M_COUNT*3-1:0] m_axi_arsize, + output wire [M_COUNT*2-1:0] m_axi_arburst, + output wire [M_COUNT-1:0] m_axi_arlock, + output wire [M_COUNT*4-1:0] m_axi_arcache, + output wire [M_COUNT*3-1:0] m_axi_arprot, + output wire [M_COUNT*4-1:0] m_axi_arqos, + output wire [M_COUNT*4-1:0] m_axi_arregion, + output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser, + output wire [M_COUNT-1:0] m_axi_arvalid, + input wire [M_COUNT-1:0] m_axi_arready, + input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid, + input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata, + input wire [M_COUNT*2-1:0] m_axi_rresp, + input wire [M_COUNT-1:0] m_axi_rlast, + input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser, + input wire [M_COUNT-1:0] m_axi_rvalid, + output wire [M_COUNT-1:0] m_axi_rready +); + +parameter CL_S_COUNT = $clog2(S_COUNT); +parameter CL_M_COUNT = $clog2(M_COUNT); +parameter M_COUNT_P1 = M_COUNT+1; +parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1); + +integer i; + +// check configuration +initial begin + if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin + $error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH (instance %m)"); + $finish; + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin + $error("Error: value out of range (instance %m)"); + $finish; + end + end +end + +wire [S_COUNT*S_ID_WIDTH-1:0] int_s_axi_arid; +wire [S_COUNT*ADDR_WIDTH-1:0] int_s_axi_araddr; +wire [S_COUNT*8-1:0] int_s_axi_arlen; +wire [S_COUNT*3-1:0] int_s_axi_arsize; +wire [S_COUNT*2-1:0] int_s_axi_arburst; +wire [S_COUNT-1:0] int_s_axi_arlock; +wire [S_COUNT*4-1:0] int_s_axi_arcache; +wire [S_COUNT*3-1:0] int_s_axi_arprot; +wire [S_COUNT*4-1:0] int_s_axi_arqos; +wire [S_COUNT*4-1:0] int_s_axi_arregion; +wire [S_COUNT*ARUSER_WIDTH-1:0] int_s_axi_aruser; +wire [S_COUNT-1:0] int_s_axi_arvalid; +wire [S_COUNT-1:0] int_s_axi_arready; + +wire [S_COUNT*M_COUNT-1:0] int_axi_arvalid; +wire [M_COUNT*S_COUNT-1:0] int_axi_arready; + +wire [M_COUNT*M_ID_WIDTH-1:0] int_m_axi_rid; +wire [M_COUNT*DATA_WIDTH-1:0] int_m_axi_rdata; +wire [M_COUNT*2-1:0] int_m_axi_rresp; +wire [M_COUNT-1:0] int_m_axi_rlast; +wire [M_COUNT*RUSER_WIDTH-1:0] int_m_axi_ruser; +wire [M_COUNT-1:0] int_m_axi_rvalid; +wire [M_COUNT-1:0] int_m_axi_rready; + +wire [M_COUNT*S_COUNT-1:0] int_axi_rvalid; +wire [S_COUNT*M_COUNT-1:0] int_axi_rready; + +generate + + genvar m, n; + + for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces + // address decode and admission control + wire [CL_M_COUNT-1:0] a_select; + + wire m_axi_avalid; + wire m_axi_aready; + + wire m_rc_decerr; + wire m_rc_valid; + wire m_rc_ready; + + wire [S_ID_WIDTH-1:0] s_cpl_id; + wire s_cpl_valid; + + axi_crossbar_addr #( + .S(m), + .S_COUNT(S_COUNT), + .M_COUNT(M_COUNT), + .ADDR_WIDTH(ADDR_WIDTH), + .ID_WIDTH(S_ID_WIDTH), + .S_THREADS(S_THREADS[m*32 +: 32]), + .S_ACCEPT(S_ACCEPT[m*32 +: 32]), + .M_REGIONS(M_REGIONS), + .M_BASE_ADDR(M_BASE_ADDR), + .M_ADDR_WIDTH(M_ADDR_WIDTH), + .M_CONNECT(M_CONNECT), + .M_SECURE(M_SECURE), + .WC_OUTPUT(0) + ) + addr_inst ( + .clk(clk), + .rst(rst), + + /* + * Address input + */ + .s_axi_aid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .s_axi_aaddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]), + .s_axi_aprot(int_s_axi_arprot[m*3 +: 3]), + .s_axi_aqos(int_s_axi_arqos[m*4 +: 4]), + .s_axi_avalid(int_s_axi_arvalid[m]), + .s_axi_aready(int_s_axi_arready[m]), + + /* + * Address output + */ + .m_axi_aregion(int_s_axi_arregion[m*4 +: 4]), + .m_select(a_select), + .m_axi_avalid(m_axi_avalid), + .m_axi_aready(m_axi_aready), + + /* + * Write command output + */ + .m_wc_select(), + .m_wc_decerr(), + .m_wc_valid(), + .m_wc_ready(1'b1), + + /* + * Response command output + */ + .m_rc_decerr(m_rc_decerr), + .m_rc_valid(m_rc_valid), + .m_rc_ready(m_rc_ready), + + /* + * Completion input + */ + .s_cpl_id(s_cpl_id), + .s_cpl_valid(s_cpl_valid) + ); + + assign int_axi_arvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select; + assign m_axi_aready = int_axi_arready[a_select*S_COUNT+m]; + + // decode error handling + reg [S_ID_WIDTH-1:0] decerr_m_axi_rid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_rid_next; + reg decerr_m_axi_rlast_reg = 1'b0, decerr_m_axi_rlast_next; + reg decerr_m_axi_rvalid_reg = 1'b0, decerr_m_axi_rvalid_next; + wire decerr_m_axi_rready; + + reg [7:0] decerr_len_reg = 8'd0, decerr_len_next; + + assign m_rc_ready = !decerr_m_axi_rvalid_reg; + + always @* begin + decerr_len_next = decerr_len_reg; + decerr_m_axi_rid_next = decerr_m_axi_rid_reg; + decerr_m_axi_rlast_next = decerr_m_axi_rlast_reg; + decerr_m_axi_rvalid_next = decerr_m_axi_rvalid_reg; + + if (decerr_m_axi_rvalid_reg) begin + if (decerr_m_axi_rready) begin + if (decerr_len_reg > 0) begin + decerr_len_next = decerr_len_reg-1; + decerr_m_axi_rlast_next = (decerr_len_next == 0); + decerr_m_axi_rvalid_next = 1'b1; + end else begin + decerr_m_axi_rvalid_next = 1'b0; + end + end + end else if (m_rc_valid && m_rc_ready) begin + decerr_len_next = int_s_axi_arlen[m*8 +: 8]; + decerr_m_axi_rid_next = int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]; + decerr_m_axi_rlast_next = (decerr_len_next == 0); + decerr_m_axi_rvalid_next = 1'b1; + end + end + + always @(posedge clk) begin + if (rst) begin + decerr_m_axi_rvalid_reg <= 1'b0; + end else begin + decerr_m_axi_rvalid_reg <= decerr_m_axi_rvalid_next; + end + + decerr_m_axi_rid_reg <= decerr_m_axi_rid_next; + decerr_m_axi_rlast_reg <= decerr_m_axi_rlast_next; + decerr_len_reg <= decerr_len_next; + end + + // read response arbitration + wire [M_COUNT_P1-1:0] r_request; + wire [M_COUNT_P1-1:0] r_acknowledge; + wire [M_COUNT_P1-1:0] r_grant; + wire r_grant_valid; + wire [CL_M_COUNT_P1-1:0] r_grant_encoded; + + arbiter #( + .PORTS(M_COUNT_P1), + .ARB_TYPE_ROUND_ROBIN(1), + .ARB_BLOCK(1), + .ARB_BLOCK_ACK(1), + .ARB_LSB_HIGH_PRIORITY(1) + ) + r_arb_inst ( + .clk(clk), + .rst(rst), + .request(r_request), + .acknowledge(r_acknowledge), + .grant(r_grant), + .grant_valid(r_grant_valid), + .grant_encoded(r_grant_encoded) + ); + + // read response mux + wire [S_ID_WIDTH-1:0] m_axi_rid_mux = {decerr_m_axi_rid_reg, int_m_axi_rid} >> r_grant_encoded*M_ID_WIDTH; + wire [DATA_WIDTH-1:0] m_axi_rdata_mux = {{DATA_WIDTH{1'b0}}, int_m_axi_rdata} >> r_grant_encoded*DATA_WIDTH; + wire [1:0] m_axi_rresp_mux = {2'b11, int_m_axi_rresp} >> r_grant_encoded*2; + wire m_axi_rlast_mux = {decerr_m_axi_rlast_reg, int_m_axi_rlast} >> r_grant_encoded; + wire [RUSER_WIDTH-1:0] m_axi_ruser_mux = {{RUSER_WIDTH{1'b0}}, int_m_axi_ruser} >> r_grant_encoded*RUSER_WIDTH; + wire m_axi_rvalid_mux = ({decerr_m_axi_rvalid_reg, int_m_axi_rvalid} >> r_grant_encoded) & r_grant_valid; + wire m_axi_rready_mux; + + assign int_axi_rready[m*M_COUNT +: M_COUNT] = (r_grant_valid && m_axi_rready_mux) << r_grant_encoded; + assign decerr_m_axi_rready = (r_grant_valid && m_axi_rready_mux) && (r_grant_encoded == M_COUNT_P1-1); + + for (n = 0; n < M_COUNT; n = n + 1) begin + assign r_request[n] = int_axi_rvalid[n*S_COUNT+m] && !r_grant[n]; + assign r_acknowledge[n] = r_grant[n] && int_axi_rvalid[n*S_COUNT+m] && m_axi_rlast_mux && m_axi_rready_mux; + end + + assign r_request[M_COUNT_P1-1] = decerr_m_axi_rvalid_reg && !r_grant[M_COUNT_P1-1]; + assign r_acknowledge[M_COUNT_P1-1] = r_grant[M_COUNT_P1-1] && decerr_m_axi_rvalid_reg && decerr_m_axi_rlast_reg && m_axi_rready_mux; + + assign s_cpl_id = m_axi_rid_mux; + assign s_cpl_valid = m_axi_rvalid_mux && m_axi_rready_mux && m_axi_rlast_mux; + + // S side register + axi_register_rd #( + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .ID_WIDTH(S_ID_WIDTH), + .ARUSER_ENABLE(ARUSER_ENABLE), + .ARUSER_WIDTH(ARUSER_WIDTH), + .RUSER_ENABLE(RUSER_ENABLE), + .RUSER_WIDTH(RUSER_WIDTH), + .AR_REG_TYPE(S_AR_REG_TYPE[m*2 +: 2]), + .R_REG_TYPE(S_R_REG_TYPE[m*2 +: 2]) + ) + reg_inst ( + .clk(clk), + .rst(rst), + .s_axi_arid(s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .s_axi_araddr(s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]), + .s_axi_arlen(s_axi_arlen[m*8 +: 8]), + .s_axi_arsize(s_axi_arsize[m*3 +: 3]), + .s_axi_arburst(s_axi_arburst[m*2 +: 2]), + .s_axi_arlock(s_axi_arlock[m]), + .s_axi_arcache(s_axi_arcache[m*4 +: 4]), + .s_axi_arprot(s_axi_arprot[m*3 +: 3]), + .s_axi_arqos(s_axi_arqos[m*4 +: 4]), + .s_axi_arregion(4'd0), + .s_axi_aruser(s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]), + .s_axi_arvalid(s_axi_arvalid[m]), + .s_axi_arready(s_axi_arready[m]), + .s_axi_rid(s_axi_rid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .s_axi_rdata(s_axi_rdata[m*DATA_WIDTH +: DATA_WIDTH]), + .s_axi_rresp(s_axi_rresp[m*2 +: 2]), + .s_axi_rlast(s_axi_rlast[m]), + .s_axi_ruser(s_axi_ruser[m*RUSER_WIDTH +: RUSER_WIDTH]), + .s_axi_rvalid(s_axi_rvalid[m]), + .s_axi_rready(s_axi_rready[m]), + .m_axi_arid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .m_axi_araddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]), + .m_axi_arlen(int_s_axi_arlen[m*8 +: 8]), + .m_axi_arsize(int_s_axi_arsize[m*3 +: 3]), + .m_axi_arburst(int_s_axi_arburst[m*2 +: 2]), + .m_axi_arlock(int_s_axi_arlock[m]), + .m_axi_arcache(int_s_axi_arcache[m*4 +: 4]), + .m_axi_arprot(int_s_axi_arprot[m*3 +: 3]), + .m_axi_arqos(int_s_axi_arqos[m*4 +: 4]), + .m_axi_arregion(), + .m_axi_aruser(int_s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]), + .m_axi_arvalid(int_s_axi_arvalid[m]), + .m_axi_arready(int_s_axi_arready[m]), + .m_axi_rid(m_axi_rid_mux), + .m_axi_rdata(m_axi_rdata_mux), + .m_axi_rresp(m_axi_rresp_mux), + .m_axi_rlast(m_axi_rlast_mux), + .m_axi_ruser(m_axi_ruser_mux), + .m_axi_rvalid(m_axi_rvalid_mux), + .m_axi_rready(m_axi_rready_mux) + ); + end // s_ifaces + + for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces + // in-flight transaction count + wire trans_start; + wire trans_complete; + reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0; + + wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete; + + always @(posedge clk) begin + if (rst) begin + trans_count_reg <= 0; + end else begin + if (trans_start && !trans_complete) begin + trans_count_reg <= trans_count_reg + 1; + end else if (!trans_start && trans_complete) begin + trans_count_reg <= trans_count_reg - 1; + end + end + end + + // address arbitration + wire [S_COUNT-1:0] a_request; + wire [S_COUNT-1:0] a_acknowledge; + wire [S_COUNT-1:0] a_grant; + wire a_grant_valid; + wire [CL_S_COUNT-1:0] a_grant_encoded; + + arbiter #( + .PORTS(S_COUNT), + .ARB_TYPE_ROUND_ROBIN(1), + .ARB_BLOCK(1), + .ARB_BLOCK_ACK(1), + .ARB_LSB_HIGH_PRIORITY(1) + ) + a_arb_inst ( + .clk(clk), + .rst(rst), + .request(a_request), + .acknowledge(a_acknowledge), + .grant(a_grant), + .grant_valid(a_grant_valid), + .grant_encoded(a_grant_encoded) + ); + + // address mux + wire [M_ID_WIDTH-1:0] s_axi_arid_mux = int_s_axi_arid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH); + wire [ADDR_WIDTH-1:0] s_axi_araddr_mux = int_s_axi_araddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH]; + wire [7:0] s_axi_arlen_mux = int_s_axi_arlen[a_grant_encoded*8 +: 8]; + wire [2:0] s_axi_arsize_mux = int_s_axi_arsize[a_grant_encoded*3 +: 3]; + wire [1:0] s_axi_arburst_mux = int_s_axi_arburst[a_grant_encoded*2 +: 2]; + wire s_axi_arlock_mux = int_s_axi_arlock[a_grant_encoded]; + wire [3:0] s_axi_arcache_mux = int_s_axi_arcache[a_grant_encoded*4 +: 4]; + wire [2:0] s_axi_arprot_mux = int_s_axi_arprot[a_grant_encoded*3 +: 3]; + wire [3:0] s_axi_arqos_mux = int_s_axi_arqos[a_grant_encoded*4 +: 4]; + wire [3:0] s_axi_arregion_mux = int_s_axi_arregion[a_grant_encoded*4 +: 4]; + wire [ARUSER_WIDTH-1:0] s_axi_aruser_mux = int_s_axi_aruser[a_grant_encoded*ARUSER_WIDTH +: ARUSER_WIDTH]; + wire s_axi_arvalid_mux = int_axi_arvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid; + wire s_axi_arready_mux; + + assign int_axi_arready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_arready_mux) << a_grant_encoded; + + for (m = 0; m < S_COUNT; m = m + 1) begin + assign a_request[m] = int_axi_arvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit; + assign a_acknowledge[m] = a_grant[m] && int_axi_arvalid[m*M_COUNT+n] && s_axi_arready_mux; + end + + assign trans_start = s_axi_arvalid_mux && s_axi_arready_mux && a_grant_valid; + + // read response forwarding + wire [CL_S_COUNT-1:0] r_select = m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH; + + assign int_axi_rvalid[n*S_COUNT +: S_COUNT] = int_m_axi_rvalid[n] << r_select; + assign int_m_axi_rready[n] = int_axi_rready[r_select*M_COUNT+n]; + + assign trans_complete = int_m_axi_rvalid[n] && int_m_axi_rready[n] && int_m_axi_rlast[n]; + + // M side register + axi_register_rd #( + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .ID_WIDTH(M_ID_WIDTH), + .ARUSER_ENABLE(ARUSER_ENABLE), + .ARUSER_WIDTH(ARUSER_WIDTH), + .RUSER_ENABLE(RUSER_ENABLE), + .RUSER_WIDTH(RUSER_WIDTH), + .AR_REG_TYPE(M_AR_REG_TYPE[n*2 +: 2]), + .R_REG_TYPE(M_R_REG_TYPE[n*2 +: 2]) + ) + reg_inst ( + .clk(clk), + .rst(rst), + .s_axi_arid(s_axi_arid_mux), + .s_axi_araddr(s_axi_araddr_mux), + .s_axi_arlen(s_axi_arlen_mux), + .s_axi_arsize(s_axi_arsize_mux), + .s_axi_arburst(s_axi_arburst_mux), + .s_axi_arlock(s_axi_arlock_mux), + .s_axi_arcache(s_axi_arcache_mux), + .s_axi_arprot(s_axi_arprot_mux), + .s_axi_arqos(s_axi_arqos_mux), + .s_axi_arregion(s_axi_arregion_mux), + .s_axi_aruser(s_axi_aruser_mux), + .s_axi_arvalid(s_axi_arvalid_mux), + .s_axi_arready(s_axi_arready_mux), + .s_axi_rid(int_m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]), + .s_axi_rdata(int_m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]), + .s_axi_rresp(int_m_axi_rresp[n*2 +: 2]), + .s_axi_rlast(int_m_axi_rlast[n]), + .s_axi_ruser(int_m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]), + .s_axi_rvalid(int_m_axi_rvalid[n]), + .s_axi_rready(int_m_axi_rready[n]), + .m_axi_arid(m_axi_arid[n*M_ID_WIDTH +: M_ID_WIDTH]), + .m_axi_araddr(m_axi_araddr[n*ADDR_WIDTH +: ADDR_WIDTH]), + .m_axi_arlen(m_axi_arlen[n*8 +: 8]), + .m_axi_arsize(m_axi_arsize[n*3 +: 3]), + .m_axi_arburst(m_axi_arburst[n*2 +: 2]), + .m_axi_arlock(m_axi_arlock[n]), + .m_axi_arcache(m_axi_arcache[n*4 +: 4]), + .m_axi_arprot(m_axi_arprot[n*3 +: 3]), + .m_axi_arqos(m_axi_arqos[n*4 +: 4]), + .m_axi_arregion(m_axi_arregion[n*4 +: 4]), + .m_axi_aruser(m_axi_aruser[n*ARUSER_WIDTH +: ARUSER_WIDTH]), + .m_axi_arvalid(m_axi_arvalid[n]), + .m_axi_arready(m_axi_arready[n]), + .m_axi_rid(m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]), + .m_axi_rdata(m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]), + .m_axi_rresp(m_axi_rresp[n*2 +: 2]), + .m_axi_rlast(m_axi_rlast[n]), + .m_axi_ruser(m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]), + .m_axi_rvalid(m_axi_rvalid[n]), + .m_axi_rready(m_axi_rready[n]) + ); + end // m_ifaces + +endgenerate + +endmodule + +`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_wr.v b/xls/modules/zstd/external/axi_crossbar_wr.v new file mode 100644 index 0000000000..5f55665351 --- /dev/null +++ b/xls/modules/zstd/external/axi_crossbar_wr.v @@ -0,0 +1,678 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 crossbar (write) + */ +module axi_crossbar_wr # +( + // Number of AXI inputs (slave interfaces) + parameter S_COUNT = 4, + // Number of AXI outputs (master interfaces) + parameter M_COUNT = 4, + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Input ID field width (from AXI masters) + parameter S_ID_WIDTH = 8, + // Output ID field width (towards AXI slaves) + // Additional bits required for response routing + parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), + // Propagate awuser signal + parameter AWUSER_ENABLE = 0, + // Width of awuser signal + parameter AWUSER_WIDTH = 1, + // Propagate wuser signal + parameter WUSER_ENABLE = 0, + // Width of wuser signal + parameter WUSER_WIDTH = 1, + // Propagate buser signal + parameter BUSER_ENABLE = 0, + // Width of buser signal + parameter BUSER_WIDTH = 1, + // Number of concurrent unique IDs for each slave interface + // S_COUNT concatenated fields of 32 bits + parameter S_THREADS = {S_COUNT{32'd2}}, + // Number of concurrent operations for each slave interface + // S_COUNT concatenated fields of 32 bits + parameter S_ACCEPT = {S_COUNT{32'd16}}, + // Number of regions per master interface + parameter M_REGIONS = 1, + // Master interface base addresses + // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits + // set to zero for default addressing based on M_ADDR_WIDTH + parameter M_BASE_ADDR = 0, + // Master interface address widths + // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits + parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, + // Write connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}}, + // Number of concurrent operations for each master interface + // M_COUNT concatenated fields of 32 bits + parameter M_ISSUE = {M_COUNT{32'd4}}, + // Secure master (fail operations based on awprot/arprot) + // M_COUNT bits + parameter M_SECURE = {M_COUNT{1'b0}}, + // Slave interface AW channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_AW_REG_TYPE = {S_COUNT{2'd0}}, + // Slave interface W channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_W_REG_TYPE = {S_COUNT{2'd0}}, + // Slave interface B channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S_B_REG_TYPE = {S_COUNT{2'd1}}, + // Master interface AW channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_AW_REG_TYPE = {M_COUNT{2'd1}}, + // Master interface W channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_W_REG_TYPE = {M_COUNT{2'd2}}, + // Master interface B channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M_B_REG_TYPE = {M_COUNT{2'd0}} +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interfaces + */ + input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr, + input wire [S_COUNT*8-1:0] s_axi_awlen, + input wire [S_COUNT*3-1:0] s_axi_awsize, + input wire [S_COUNT*2-1:0] s_axi_awburst, + input wire [S_COUNT-1:0] s_axi_awlock, + input wire [S_COUNT*4-1:0] s_axi_awcache, + input wire [S_COUNT*3-1:0] s_axi_awprot, + input wire [S_COUNT*4-1:0] s_axi_awqos, + input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser, + input wire [S_COUNT-1:0] s_axi_awvalid, + output wire [S_COUNT-1:0] s_axi_awready, + input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata, + input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb, + input wire [S_COUNT-1:0] s_axi_wlast, + input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser, + input wire [S_COUNT-1:0] s_axi_wvalid, + output wire [S_COUNT-1:0] s_axi_wready, + output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid, + output wire [S_COUNT*2-1:0] s_axi_bresp, + output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser, + output wire [S_COUNT-1:0] s_axi_bvalid, + input wire [S_COUNT-1:0] s_axi_bready, + + /* + * AXI master interfaces + */ + output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [M_COUNT*8-1:0] m_axi_awlen, + output wire [M_COUNT*3-1:0] m_axi_awsize, + output wire [M_COUNT*2-1:0] m_axi_awburst, + output wire [M_COUNT-1:0] m_axi_awlock, + output wire [M_COUNT*4-1:0] m_axi_awcache, + output wire [M_COUNT*3-1:0] m_axi_awprot, + output wire [M_COUNT*4-1:0] m_axi_awqos, + output wire [M_COUNT*4-1:0] m_axi_awregion, + output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser, + output wire [M_COUNT-1:0] m_axi_awvalid, + input wire [M_COUNT-1:0] m_axi_awready, + output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata, + output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb, + output wire [M_COUNT-1:0] m_axi_wlast, + output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser, + output wire [M_COUNT-1:0] m_axi_wvalid, + input wire [M_COUNT-1:0] m_axi_wready, + input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid, + input wire [M_COUNT*2-1:0] m_axi_bresp, + input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser, + input wire [M_COUNT-1:0] m_axi_bvalid, + output wire [M_COUNT-1:0] m_axi_bready +); + +parameter CL_S_COUNT = $clog2(S_COUNT); +parameter CL_M_COUNT = $clog2(M_COUNT); +parameter M_COUNT_P1 = M_COUNT+1; +parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1); + +integer i; + +// check configuration +initial begin + if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin + $error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH (instance %m)"); + $finish; + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin + $error("Error: value out of range (instance %m)"); + $finish; + end + end +end + +wire [S_COUNT*S_ID_WIDTH-1:0] int_s_axi_awid; +wire [S_COUNT*ADDR_WIDTH-1:0] int_s_axi_awaddr; +wire [S_COUNT*8-1:0] int_s_axi_awlen; +wire [S_COUNT*3-1:0] int_s_axi_awsize; +wire [S_COUNT*2-1:0] int_s_axi_awburst; +wire [S_COUNT-1:0] int_s_axi_awlock; +wire [S_COUNT*4-1:0] int_s_axi_awcache; +wire [S_COUNT*3-1:0] int_s_axi_awprot; +wire [S_COUNT*4-1:0] int_s_axi_awqos; +wire [S_COUNT*4-1:0] int_s_axi_awregion; +wire [S_COUNT*AWUSER_WIDTH-1:0] int_s_axi_awuser; +wire [S_COUNT-1:0] int_s_axi_awvalid; +wire [S_COUNT-1:0] int_s_axi_awready; + +wire [S_COUNT*M_COUNT-1:0] int_axi_awvalid; +wire [M_COUNT*S_COUNT-1:0] int_axi_awready; + +wire [S_COUNT*DATA_WIDTH-1:0] int_s_axi_wdata; +wire [S_COUNT*STRB_WIDTH-1:0] int_s_axi_wstrb; +wire [S_COUNT-1:0] int_s_axi_wlast; +wire [S_COUNT*WUSER_WIDTH-1:0] int_s_axi_wuser; +wire [S_COUNT-1:0] int_s_axi_wvalid; +wire [S_COUNT-1:0] int_s_axi_wready; + +wire [S_COUNT*M_COUNT-1:0] int_axi_wvalid; +wire [M_COUNT*S_COUNT-1:0] int_axi_wready; + +wire [M_COUNT*M_ID_WIDTH-1:0] int_m_axi_bid; +wire [M_COUNT*2-1:0] int_m_axi_bresp; +wire [M_COUNT*BUSER_WIDTH-1:0] int_m_axi_buser; +wire [M_COUNT-1:0] int_m_axi_bvalid; +wire [M_COUNT-1:0] int_m_axi_bready; + +wire [M_COUNT*S_COUNT-1:0] int_axi_bvalid; +wire [S_COUNT*M_COUNT-1:0] int_axi_bready; + +generate + + genvar m, n; + + for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces + // address decode and admission control + wire [CL_M_COUNT-1:0] a_select; + + wire m_axi_avalid; + wire m_axi_aready; + + wire [CL_M_COUNT-1:0] m_wc_select; + wire m_wc_decerr; + wire m_wc_valid; + wire m_wc_ready; + + wire m_rc_decerr; + wire m_rc_valid; + wire m_rc_ready; + + wire [S_ID_WIDTH-1:0] s_cpl_id; + wire s_cpl_valid; + + axi_crossbar_addr #( + .S(m), + .S_COUNT(S_COUNT), + .M_COUNT(M_COUNT), + .ADDR_WIDTH(ADDR_WIDTH), + .ID_WIDTH(S_ID_WIDTH), + .S_THREADS(S_THREADS[m*32 +: 32]), + .S_ACCEPT(S_ACCEPT[m*32 +: 32]), + .M_REGIONS(M_REGIONS), + .M_BASE_ADDR(M_BASE_ADDR), + .M_ADDR_WIDTH(M_ADDR_WIDTH), + .M_CONNECT(M_CONNECT), + .M_SECURE(M_SECURE), + .WC_OUTPUT(1) + ) + addr_inst ( + .clk(clk), + .rst(rst), + + /* + * Address input + */ + .s_axi_aid(int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .s_axi_aaddr(int_s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]), + .s_axi_aprot(int_s_axi_awprot[m*3 +: 3]), + .s_axi_aqos(int_s_axi_awqos[m*4 +: 4]), + .s_axi_avalid(int_s_axi_awvalid[m]), + .s_axi_aready(int_s_axi_awready[m]), + + /* + * Address output + */ + .m_axi_aregion(int_s_axi_awregion[m*4 +: 4]), + .m_select(a_select), + .m_axi_avalid(m_axi_avalid), + .m_axi_aready(m_axi_aready), + + /* + * Write command output + */ + .m_wc_select(m_wc_select), + .m_wc_decerr(m_wc_decerr), + .m_wc_valid(m_wc_valid), + .m_wc_ready(m_wc_ready), + + /* + * Response command output + */ + .m_rc_decerr(m_rc_decerr), + .m_rc_valid(m_rc_valid), + .m_rc_ready(m_rc_ready), + + /* + * Completion input + */ + .s_cpl_id(s_cpl_id), + .s_cpl_valid(s_cpl_valid) + ); + + assign int_axi_awvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select; + assign m_axi_aready = int_axi_awready[a_select*S_COUNT+m]; + + // write command handling + reg [CL_M_COUNT-1:0] w_select_reg = 0, w_select_next; + reg w_drop_reg = 1'b0, w_drop_next; + reg w_select_valid_reg = 1'b0, w_select_valid_next; + + assign m_wc_ready = !w_select_valid_reg; + + always @* begin + w_select_next = w_select_reg; + w_drop_next = w_drop_reg && !(int_s_axi_wvalid[m] && int_s_axi_wready[m] && int_s_axi_wlast[m]); + w_select_valid_next = w_select_valid_reg && !(int_s_axi_wvalid[m] && int_s_axi_wready[m] && int_s_axi_wlast[m]); + + if (m_wc_valid && !w_select_valid_reg) begin + w_select_next = m_wc_select; + w_drop_next = m_wc_decerr; + w_select_valid_next = m_wc_valid; + end + end + + always @(posedge clk) begin + if (rst) begin + w_select_valid_reg <= 1'b0; + end else begin + w_select_valid_reg <= w_select_valid_next; + end + + w_select_reg <= w_select_next; + w_drop_reg <= w_drop_next; + end + + // write data forwarding + assign int_axi_wvalid[m*M_COUNT +: M_COUNT] = (int_s_axi_wvalid[m] && w_select_valid_reg && !w_drop_reg) << w_select_reg; + assign int_s_axi_wready[m] = int_axi_wready[w_select_reg*S_COUNT+m] || w_drop_reg; + + // decode error handling + reg [S_ID_WIDTH-1:0] decerr_m_axi_bid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_bid_next; + reg decerr_m_axi_bvalid_reg = 1'b0, decerr_m_axi_bvalid_next; + wire decerr_m_axi_bready; + + assign m_rc_ready = !decerr_m_axi_bvalid_reg; + + always @* begin + decerr_m_axi_bid_next = decerr_m_axi_bid_reg; + decerr_m_axi_bvalid_next = decerr_m_axi_bvalid_reg; + + if (decerr_m_axi_bvalid_reg) begin + if (decerr_m_axi_bready) begin + decerr_m_axi_bvalid_next = 1'b0; + end + end else if (m_rc_valid && m_rc_ready) begin + decerr_m_axi_bid_next = int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]; + decerr_m_axi_bvalid_next = 1'b1; + end + end + + always @(posedge clk) begin + if (rst) begin + decerr_m_axi_bvalid_reg <= 1'b0; + end else begin + decerr_m_axi_bvalid_reg <= decerr_m_axi_bvalid_next; + end + + decerr_m_axi_bid_reg <= decerr_m_axi_bid_next; + end + + // write response arbitration + wire [M_COUNT_P1-1:0] b_request; + wire [M_COUNT_P1-1:0] b_acknowledge; + wire [M_COUNT_P1-1:0] b_grant; + wire b_grant_valid; + wire [CL_M_COUNT_P1-1:0] b_grant_encoded; + + arbiter #( + .PORTS(M_COUNT_P1), + .ARB_TYPE_ROUND_ROBIN(1), + .ARB_BLOCK(1), + .ARB_BLOCK_ACK(1), + .ARB_LSB_HIGH_PRIORITY(1) + ) + b_arb_inst ( + .clk(clk), + .rst(rst), + .request(b_request), + .acknowledge(b_acknowledge), + .grant(b_grant), + .grant_valid(b_grant_valid), + .grant_encoded(b_grant_encoded) + ); + + // write response mux + wire [S_ID_WIDTH-1:0] m_axi_bid_mux = {decerr_m_axi_bid_reg, int_m_axi_bid} >> b_grant_encoded*M_ID_WIDTH; + wire [1:0] m_axi_bresp_mux = {2'b11, int_m_axi_bresp} >> b_grant_encoded*2; + wire [BUSER_WIDTH-1:0] m_axi_buser_mux = {{BUSER_WIDTH{1'b0}}, int_m_axi_buser} >> b_grant_encoded*BUSER_WIDTH; + wire m_axi_bvalid_mux = ({decerr_m_axi_bvalid_reg, int_m_axi_bvalid} >> b_grant_encoded) & b_grant_valid; + wire m_axi_bready_mux; + + assign int_axi_bready[m*M_COUNT +: M_COUNT] = (b_grant_valid && m_axi_bready_mux) << b_grant_encoded; + assign decerr_m_axi_bready = (b_grant_valid && m_axi_bready_mux) && (b_grant_encoded == M_COUNT_P1-1); + + for (n = 0; n < M_COUNT; n = n + 1) begin + assign b_request[n] = int_axi_bvalid[n*S_COUNT+m] && !b_grant[n]; + assign b_acknowledge[n] = b_grant[n] && int_axi_bvalid[n*S_COUNT+m] && m_axi_bready_mux; + end + + assign b_request[M_COUNT_P1-1] = decerr_m_axi_bvalid_reg && !b_grant[M_COUNT_P1-1]; + assign b_acknowledge[M_COUNT_P1-1] = b_grant[M_COUNT_P1-1] && decerr_m_axi_bvalid_reg && m_axi_bready_mux; + + assign s_cpl_id = m_axi_bid_mux; + assign s_cpl_valid = m_axi_bvalid_mux && m_axi_bready_mux; + + // S side register + axi_register_wr #( + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .ID_WIDTH(S_ID_WIDTH), + .AWUSER_ENABLE(AWUSER_ENABLE), + .AWUSER_WIDTH(AWUSER_WIDTH), + .WUSER_ENABLE(WUSER_ENABLE), + .WUSER_WIDTH(WUSER_WIDTH), + .BUSER_ENABLE(BUSER_ENABLE), + .BUSER_WIDTH(BUSER_WIDTH), + .AW_REG_TYPE(S_AW_REG_TYPE[m*2 +: 2]), + .W_REG_TYPE(S_W_REG_TYPE[m*2 +: 2]), + .B_REG_TYPE(S_B_REG_TYPE[m*2 +: 2]) + ) + reg_inst ( + .clk(clk), + .rst(rst), + .s_axi_awid(s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .s_axi_awaddr(s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]), + .s_axi_awlen(s_axi_awlen[m*8 +: 8]), + .s_axi_awsize(s_axi_awsize[m*3 +: 3]), + .s_axi_awburst(s_axi_awburst[m*2 +: 2]), + .s_axi_awlock(s_axi_awlock[m]), + .s_axi_awcache(s_axi_awcache[m*4 +: 4]), + .s_axi_awprot(s_axi_awprot[m*3 +: 3]), + .s_axi_awqos(s_axi_awqos[m*4 +: 4]), + .s_axi_awregion(4'd0), + .s_axi_awuser(s_axi_awuser[m*AWUSER_WIDTH +: AWUSER_WIDTH]), + .s_axi_awvalid(s_axi_awvalid[m]), + .s_axi_awready(s_axi_awready[m]), + .s_axi_wdata(s_axi_wdata[m*DATA_WIDTH +: DATA_WIDTH]), + .s_axi_wstrb(s_axi_wstrb[m*STRB_WIDTH +: STRB_WIDTH]), + .s_axi_wlast(s_axi_wlast[m]), + .s_axi_wuser(s_axi_wuser[m*WUSER_WIDTH +: WUSER_WIDTH]), + .s_axi_wvalid(s_axi_wvalid[m]), + .s_axi_wready(s_axi_wready[m]), + .s_axi_bid(s_axi_bid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .s_axi_bresp(s_axi_bresp[m*2 +: 2]), + .s_axi_buser(s_axi_buser[m*BUSER_WIDTH +: BUSER_WIDTH]), + .s_axi_bvalid(s_axi_bvalid[m]), + .s_axi_bready(s_axi_bready[m]), + .m_axi_awid(int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]), + .m_axi_awaddr(int_s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]), + .m_axi_awlen(int_s_axi_awlen[m*8 +: 8]), + .m_axi_awsize(int_s_axi_awsize[m*3 +: 3]), + .m_axi_awburst(int_s_axi_awburst[m*2 +: 2]), + .m_axi_awlock(int_s_axi_awlock[m]), + .m_axi_awcache(int_s_axi_awcache[m*4 +: 4]), + .m_axi_awprot(int_s_axi_awprot[m*3 +: 3]), + .m_axi_awqos(int_s_axi_awqos[m*4 +: 4]), + .m_axi_awregion(), + .m_axi_awuser(int_s_axi_awuser[m*AWUSER_WIDTH +: AWUSER_WIDTH]), + .m_axi_awvalid(int_s_axi_awvalid[m]), + .m_axi_awready(int_s_axi_awready[m]), + .m_axi_wdata(int_s_axi_wdata[m*DATA_WIDTH +: DATA_WIDTH]), + .m_axi_wstrb(int_s_axi_wstrb[m*STRB_WIDTH +: STRB_WIDTH]), + .m_axi_wlast(int_s_axi_wlast[m]), + .m_axi_wuser(int_s_axi_wuser[m*WUSER_WIDTH +: WUSER_WIDTH]), + .m_axi_wvalid(int_s_axi_wvalid[m]), + .m_axi_wready(int_s_axi_wready[m]), + .m_axi_bid(m_axi_bid_mux), + .m_axi_bresp(m_axi_bresp_mux), + .m_axi_buser(m_axi_buser_mux), + .m_axi_bvalid(m_axi_bvalid_mux), + .m_axi_bready(m_axi_bready_mux) + ); + end // s_ifaces + + for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces + // in-flight transaction count + wire trans_start; + wire trans_complete; + reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0; + + wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete; + + always @(posedge clk) begin + if (rst) begin + trans_count_reg <= 0; + end else begin + if (trans_start && !trans_complete) begin + trans_count_reg <= trans_count_reg + 1; + end else if (!trans_start && trans_complete) begin + trans_count_reg <= trans_count_reg - 1; + end + end + end + + // address arbitration + reg [CL_S_COUNT-1:0] w_select_reg = 0, w_select_next; + reg w_select_valid_reg = 1'b0, w_select_valid_next; + reg w_select_new_reg = 1'b0, w_select_new_next; + + wire [S_COUNT-1:0] a_request; + wire [S_COUNT-1:0] a_acknowledge; + wire [S_COUNT-1:0] a_grant; + wire a_grant_valid; + wire [CL_S_COUNT-1:0] a_grant_encoded; + + arbiter #( + .PORTS(S_COUNT), + .ARB_TYPE_ROUND_ROBIN(1), + .ARB_BLOCK(1), + .ARB_BLOCK_ACK(1), + .ARB_LSB_HIGH_PRIORITY(1) + ) + a_arb_inst ( + .clk(clk), + .rst(rst), + .request(a_request), + .acknowledge(a_acknowledge), + .grant(a_grant), + .grant_valid(a_grant_valid), + .grant_encoded(a_grant_encoded) + ); + + // address mux + wire [M_ID_WIDTH-1:0] s_axi_awid_mux = int_s_axi_awid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH); + wire [ADDR_WIDTH-1:0] s_axi_awaddr_mux = int_s_axi_awaddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH]; + wire [7:0] s_axi_awlen_mux = int_s_axi_awlen[a_grant_encoded*8 +: 8]; + wire [2:0] s_axi_awsize_mux = int_s_axi_awsize[a_grant_encoded*3 +: 3]; + wire [1:0] s_axi_awburst_mux = int_s_axi_awburst[a_grant_encoded*2 +: 2]; + wire s_axi_awlock_mux = int_s_axi_awlock[a_grant_encoded]; + wire [3:0] s_axi_awcache_mux = int_s_axi_awcache[a_grant_encoded*4 +: 4]; + wire [2:0] s_axi_awprot_mux = int_s_axi_awprot[a_grant_encoded*3 +: 3]; + wire [3:0] s_axi_awqos_mux = int_s_axi_awqos[a_grant_encoded*4 +: 4]; + wire [3:0] s_axi_awregion_mux = int_s_axi_awregion[a_grant_encoded*4 +: 4]; + wire [AWUSER_WIDTH-1:0] s_axi_awuser_mux = int_s_axi_awuser[a_grant_encoded*AWUSER_WIDTH +: AWUSER_WIDTH]; + wire s_axi_awvalid_mux = int_axi_awvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid; + wire s_axi_awready_mux; + + assign int_axi_awready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_awready_mux) << a_grant_encoded; + + for (m = 0; m < S_COUNT; m = m + 1) begin + assign a_request[m] = int_axi_awvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit && !w_select_valid_next; + assign a_acknowledge[m] = a_grant[m] && int_axi_awvalid[m*M_COUNT+n] && s_axi_awready_mux; + end + + assign trans_start = s_axi_awvalid_mux && s_axi_awready_mux && a_grant_valid; + + // write data mux + wire [DATA_WIDTH-1:0] s_axi_wdata_mux = int_s_axi_wdata[w_select_reg*DATA_WIDTH +: DATA_WIDTH]; + wire [STRB_WIDTH-1:0] s_axi_wstrb_mux = int_s_axi_wstrb[w_select_reg*STRB_WIDTH +: STRB_WIDTH]; + wire s_axi_wlast_mux = int_s_axi_wlast[w_select_reg]; + wire [WUSER_WIDTH-1:0] s_axi_wuser_mux = int_s_axi_wuser[w_select_reg*WUSER_WIDTH +: WUSER_WIDTH]; + wire s_axi_wvalid_mux = int_axi_wvalid[w_select_reg*M_COUNT+n] && w_select_valid_reg; + wire s_axi_wready_mux; + + assign int_axi_wready[n*S_COUNT +: S_COUNT] = (w_select_valid_reg && s_axi_wready_mux) << w_select_reg; + + // write data routing + always @* begin + w_select_next = w_select_reg; + w_select_valid_next = w_select_valid_reg && !(s_axi_wvalid_mux && s_axi_wready_mux && s_axi_wlast_mux); + w_select_new_next = w_select_new_reg || !a_grant_valid || a_acknowledge; + + if (a_grant_valid && !w_select_valid_reg && w_select_new_reg) begin + w_select_next = a_grant_encoded; + w_select_valid_next = a_grant_valid; + w_select_new_next = 1'b0; + end + end + + always @(posedge clk) begin + if (rst) begin + w_select_valid_reg <= 1'b0; + w_select_new_reg <= 1'b1; + end else begin + w_select_valid_reg <= w_select_valid_next; + w_select_new_reg <= w_select_new_next; + end + + w_select_reg <= w_select_next; + end + + // write response forwarding + wire [CL_S_COUNT-1:0] b_select = m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH; + + assign int_axi_bvalid[n*S_COUNT +: S_COUNT] = int_m_axi_bvalid[n] << b_select; + assign int_m_axi_bready[n] = int_axi_bready[b_select*M_COUNT+n]; + + assign trans_complete = int_m_axi_bvalid[n] && int_m_axi_bready[n]; + + // M side register + axi_register_wr #( + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH), + .STRB_WIDTH(STRB_WIDTH), + .ID_WIDTH(M_ID_WIDTH), + .AWUSER_ENABLE(AWUSER_ENABLE), + .AWUSER_WIDTH(AWUSER_WIDTH), + .WUSER_ENABLE(WUSER_ENABLE), + .WUSER_WIDTH(WUSER_WIDTH), + .BUSER_ENABLE(BUSER_ENABLE), + .BUSER_WIDTH(BUSER_WIDTH), + .AW_REG_TYPE(M_AW_REG_TYPE[n*2 +: 2]), + .W_REG_TYPE(M_W_REG_TYPE[n*2 +: 2]), + .B_REG_TYPE(M_B_REG_TYPE[n*2 +: 2]) + ) + reg_inst ( + .clk(clk), + .rst(rst), + .s_axi_awid(s_axi_awid_mux), + .s_axi_awaddr(s_axi_awaddr_mux), + .s_axi_awlen(s_axi_awlen_mux), + .s_axi_awsize(s_axi_awsize_mux), + .s_axi_awburst(s_axi_awburst_mux), + .s_axi_awlock(s_axi_awlock_mux), + .s_axi_awcache(s_axi_awcache_mux), + .s_axi_awprot(s_axi_awprot_mux), + .s_axi_awqos(s_axi_awqos_mux), + .s_axi_awregion(s_axi_awregion_mux), + .s_axi_awuser(s_axi_awuser_mux), + .s_axi_awvalid(s_axi_awvalid_mux), + .s_axi_awready(s_axi_awready_mux), + .s_axi_wdata(s_axi_wdata_mux), + .s_axi_wstrb(s_axi_wstrb_mux), + .s_axi_wlast(s_axi_wlast_mux), + .s_axi_wuser(s_axi_wuser_mux), + .s_axi_wvalid(s_axi_wvalid_mux), + .s_axi_wready(s_axi_wready_mux), + .s_axi_bid(int_m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH]), + .s_axi_bresp(int_m_axi_bresp[n*2 +: 2]), + .s_axi_buser(int_m_axi_buser[n*BUSER_WIDTH +: BUSER_WIDTH]), + .s_axi_bvalid(int_m_axi_bvalid[n]), + .s_axi_bready(int_m_axi_bready[n]), + .m_axi_awid(m_axi_awid[n*M_ID_WIDTH +: M_ID_WIDTH]), + .m_axi_awaddr(m_axi_awaddr[n*ADDR_WIDTH +: ADDR_WIDTH]), + .m_axi_awlen(m_axi_awlen[n*8 +: 8]), + .m_axi_awsize(m_axi_awsize[n*3 +: 3]), + .m_axi_awburst(m_axi_awburst[n*2 +: 2]), + .m_axi_awlock(m_axi_awlock[n]), + .m_axi_awcache(m_axi_awcache[n*4 +: 4]), + .m_axi_awprot(m_axi_awprot[n*3 +: 3]), + .m_axi_awqos(m_axi_awqos[n*4 +: 4]), + .m_axi_awregion(m_axi_awregion[n*4 +: 4]), + .m_axi_awuser(m_axi_awuser[n*AWUSER_WIDTH +: AWUSER_WIDTH]), + .m_axi_awvalid(m_axi_awvalid[n]), + .m_axi_awready(m_axi_awready[n]), + .m_axi_wdata(m_axi_wdata[n*DATA_WIDTH +: DATA_WIDTH]), + .m_axi_wstrb(m_axi_wstrb[n*STRB_WIDTH +: STRB_WIDTH]), + .m_axi_wlast(m_axi_wlast[n]), + .m_axi_wuser(m_axi_wuser[n*WUSER_WIDTH +: WUSER_WIDTH]), + .m_axi_wvalid(m_axi_wvalid[n]), + .m_axi_wready(m_axi_wready[n]), + .m_axi_bid(m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH]), + .m_axi_bresp(m_axi_bresp[n*2 +: 2]), + .m_axi_buser(m_axi_buser[n*BUSER_WIDTH +: BUSER_WIDTH]), + .m_axi_bvalid(m_axi_bvalid[n]), + .m_axi_bready(m_axi_bready[n]) + ); + end // m_ifaces + +endgenerate + +endmodule + +`resetall diff --git a/xls/modules/zstd/axi_interconnect_wrapper.v b/xls/modules/zstd/external/axi_crossbar_wrapper.v similarity index 70% rename from xls/modules/zstd/axi_interconnect_wrapper.v rename to xls/modules/zstd/external/axi_crossbar_wrapper.v index 50017314f9..c244575e98 100644 --- a/xls/modules/zstd/axi_interconnect_wrapper.v +++ b/xls/modules/zstd/external/axi_crossbar_wrapper.v @@ -29,31 +29,150 @@ THE SOFTWARE. `default_nettype none /* - * AXI4 4x1 interconnect (wrapper) + * AXI4 4x1 crossbar (wrapper) */ -module axi_interconnect_wrapper # +module axi_crossbar_wrapper # ( + // Width of data bus in bits parameter DATA_WIDTH = 32, + // Width of address bus in bits parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) parameter STRB_WIDTH = (DATA_WIDTH/8), - parameter ID_WIDTH = 8, + // Input ID field width (from AXI masters) + parameter S_ID_WIDTH = 8, + // Output ID field width (towards AXI slaves) + // Additional bits required for response routing + parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), + // Propagate awuser signal parameter AWUSER_ENABLE = 0, + // Width of awuser signal parameter AWUSER_WIDTH = 1, + // Propagate wuser signal parameter WUSER_ENABLE = 0, + // Width of wuser signal parameter WUSER_WIDTH = 1, + // Propagate buser signal parameter BUSER_ENABLE = 0, + // Width of buser signal parameter BUSER_WIDTH = 1, + // Propagate aruser signal parameter ARUSER_ENABLE = 0, + // Width of aruser signal parameter ARUSER_WIDTH = 1, + // Propagate ruser signal parameter RUSER_ENABLE = 0, + // Width of ruser signal parameter RUSER_WIDTH = 1, - parameter FORWARD_ID = 0, + // Number of concurrent unique IDs + parameter S00_THREADS = 2, + // Number of concurrent operations + parameter S00_ACCEPT = 16, + // Number of concurrent unique IDs + parameter S01_THREADS = 2, + // Number of concurrent operations + parameter S01_ACCEPT = 16, + // Number of concurrent unique IDs + parameter S02_THREADS = 2, + // Number of concurrent operations + parameter S02_ACCEPT = 16, + // Number of concurrent unique IDs + parameter S03_THREADS = 2, + // Number of concurrent operations + parameter S03_ACCEPT = 16, + // Number of regions per master interface parameter M_REGIONS = 1, + // Master interface base addresses + // M_REGIONS concatenated fields of ADDR_WIDTH bits parameter M00_BASE_ADDR = 0, + // Master interface address widths + // M_REGIONS concatenated fields of 32 bits parameter M00_ADDR_WIDTH = {M_REGIONS{32'd24}}, + // Read connections between interfaces + // S_COUNT bits parameter M00_CONNECT_READ = 4'b1111, + // Write connections between interfaces + // S_COUNT bits parameter M00_CONNECT_WRITE = 4'b1111, - parameter M00_SECURE = 1'b0 + // Number of concurrent operations for each master interface + parameter M00_ISSUE = 4, + // Secure master (fail operations based on awprot/arprot) + parameter M00_SECURE = 0, + // Slave interface AW channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S00_AW_REG_TYPE = 0, + // Slave interface W channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S00_W_REG_TYPE = 0, + // Slave interface B channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S00_B_REG_TYPE = 1, + // Slave interface AR channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S00_AR_REG_TYPE = 0, + // Slave interface R channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S00_R_REG_TYPE = 2, + // Slave interface AW channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S01_AW_REG_TYPE = 0, + // Slave interface W channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S01_W_REG_TYPE = 0, + // Slave interface B channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S01_B_REG_TYPE = 1, + // Slave interface AR channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S01_AR_REG_TYPE = 0, + // Slave interface R channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S01_R_REG_TYPE = 2, + // Slave interface AW channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S02_AW_REG_TYPE = 0, + // Slave interface W channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S02_W_REG_TYPE = 0, + // Slave interface B channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S02_B_REG_TYPE = 1, + // Slave interface AR channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S02_AR_REG_TYPE = 0, + // Slave interface R channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S02_R_REG_TYPE = 2, + // Slave interface AW channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S03_AW_REG_TYPE = 0, + // Slave interface W channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S03_W_REG_TYPE = 0, + // Slave interface B channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S03_B_REG_TYPE = 1, + // Slave interface AR channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S03_AR_REG_TYPE = 0, + // Slave interface R channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter S03_R_REG_TYPE = 2, + // Master interface AW channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M00_AW_REG_TYPE = 1, + // Master interface W channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M00_W_REG_TYPE = 2, + // Master interface B channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M00_B_REG_TYPE = 0, + // Master interface AR channel register type (output) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M00_AR_REG_TYPE = 1, + // Master interface R channel register type (input) + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter M00_R_REG_TYPE = 0 ) ( input wire clk, @@ -62,7 +181,7 @@ module axi_interconnect_wrapper # /* * AXI slave interface */ - input wire [ID_WIDTH-1:0] s00_axi_awid, + input wire [S_ID_WIDTH-1:0] s00_axi_awid, input wire [ADDR_WIDTH-1:0] s00_axi_awaddr, input wire [7:0] s00_axi_awlen, input wire [2:0] s00_axi_awsize, @@ -80,12 +199,12 @@ module axi_interconnect_wrapper # input wire [WUSER_WIDTH-1:0] s00_axi_wuser, input wire s00_axi_wvalid, output wire s00_axi_wready, - output wire [ID_WIDTH-1:0] s00_axi_bid, + output wire [S_ID_WIDTH-1:0] s00_axi_bid, output wire [1:0] s00_axi_bresp, output wire [BUSER_WIDTH-1:0] s00_axi_buser, output wire s00_axi_bvalid, input wire s00_axi_bready, - input wire [ID_WIDTH-1:0] s00_axi_arid, + input wire [S_ID_WIDTH-1:0] s00_axi_arid, input wire [ADDR_WIDTH-1:0] s00_axi_araddr, input wire [7:0] s00_axi_arlen, input wire [2:0] s00_axi_arsize, @@ -97,7 +216,7 @@ module axi_interconnect_wrapper # input wire [ARUSER_WIDTH-1:0] s00_axi_aruser, input wire s00_axi_arvalid, output wire s00_axi_arready, - output wire [ID_WIDTH-1:0] s00_axi_rid, + output wire [S_ID_WIDTH-1:0] s00_axi_rid, output wire [DATA_WIDTH-1:0] s00_axi_rdata, output wire [1:0] s00_axi_rresp, output wire s00_axi_rlast, @@ -105,7 +224,7 @@ module axi_interconnect_wrapper # output wire s00_axi_rvalid, input wire s00_axi_rready, - input wire [ID_WIDTH-1:0] s01_axi_awid, + input wire [S_ID_WIDTH-1:0] s01_axi_awid, input wire [ADDR_WIDTH-1:0] s01_axi_awaddr, input wire [7:0] s01_axi_awlen, input wire [2:0] s01_axi_awsize, @@ -123,12 +242,12 @@ module axi_interconnect_wrapper # input wire [WUSER_WIDTH-1:0] s01_axi_wuser, input wire s01_axi_wvalid, output wire s01_axi_wready, - output wire [ID_WIDTH-1:0] s01_axi_bid, + output wire [S_ID_WIDTH-1:0] s01_axi_bid, output wire [1:0] s01_axi_bresp, output wire [BUSER_WIDTH-1:0] s01_axi_buser, output wire s01_axi_bvalid, input wire s01_axi_bready, - input wire [ID_WIDTH-1:0] s01_axi_arid, + input wire [S_ID_WIDTH-1:0] s01_axi_arid, input wire [ADDR_WIDTH-1:0] s01_axi_araddr, input wire [7:0] s01_axi_arlen, input wire [2:0] s01_axi_arsize, @@ -140,7 +259,7 @@ module axi_interconnect_wrapper # input wire [ARUSER_WIDTH-1:0] s01_axi_aruser, input wire s01_axi_arvalid, output wire s01_axi_arready, - output wire [ID_WIDTH-1:0] s01_axi_rid, + output wire [S_ID_WIDTH-1:0] s01_axi_rid, output wire [DATA_WIDTH-1:0] s01_axi_rdata, output wire [1:0] s01_axi_rresp, output wire s01_axi_rlast, @@ -148,7 +267,7 @@ module axi_interconnect_wrapper # output wire s01_axi_rvalid, input wire s01_axi_rready, - input wire [ID_WIDTH-1:0] s02_axi_awid, + input wire [S_ID_WIDTH-1:0] s02_axi_awid, input wire [ADDR_WIDTH-1:0] s02_axi_awaddr, input wire [7:0] s02_axi_awlen, input wire [2:0] s02_axi_awsize, @@ -166,12 +285,12 @@ module axi_interconnect_wrapper # input wire [WUSER_WIDTH-1:0] s02_axi_wuser, input wire s02_axi_wvalid, output wire s02_axi_wready, - output wire [ID_WIDTH-1:0] s02_axi_bid, + output wire [S_ID_WIDTH-1:0] s02_axi_bid, output wire [1:0] s02_axi_bresp, output wire [BUSER_WIDTH-1:0] s02_axi_buser, output wire s02_axi_bvalid, input wire s02_axi_bready, - input wire [ID_WIDTH-1:0] s02_axi_arid, + input wire [S_ID_WIDTH-1:0] s02_axi_arid, input wire [ADDR_WIDTH-1:0] s02_axi_araddr, input wire [7:0] s02_axi_arlen, input wire [2:0] s02_axi_arsize, @@ -183,7 +302,7 @@ module axi_interconnect_wrapper # input wire [ARUSER_WIDTH-1:0] s02_axi_aruser, input wire s02_axi_arvalid, output wire s02_axi_arready, - output wire [ID_WIDTH-1:0] s02_axi_rid, + output wire [S_ID_WIDTH-1:0] s02_axi_rid, output wire [DATA_WIDTH-1:0] s02_axi_rdata, output wire [1:0] s02_axi_rresp, output wire s02_axi_rlast, @@ -191,7 +310,7 @@ module axi_interconnect_wrapper # output wire s02_axi_rvalid, input wire s02_axi_rready, - input wire [ID_WIDTH-1:0] s03_axi_awid, + input wire [S_ID_WIDTH-1:0] s03_axi_awid, input wire [ADDR_WIDTH-1:0] s03_axi_awaddr, input wire [7:0] s03_axi_awlen, input wire [2:0] s03_axi_awsize, @@ -209,12 +328,12 @@ module axi_interconnect_wrapper # input wire [WUSER_WIDTH-1:0] s03_axi_wuser, input wire s03_axi_wvalid, output wire s03_axi_wready, - output wire [ID_WIDTH-1:0] s03_axi_bid, + output wire [S_ID_WIDTH-1:0] s03_axi_bid, output wire [1:0] s03_axi_bresp, output wire [BUSER_WIDTH-1:0] s03_axi_buser, output wire s03_axi_bvalid, input wire s03_axi_bready, - input wire [ID_WIDTH-1:0] s03_axi_arid, + input wire [S_ID_WIDTH-1:0] s03_axi_arid, input wire [ADDR_WIDTH-1:0] s03_axi_araddr, input wire [7:0] s03_axi_arlen, input wire [2:0] s03_axi_arsize, @@ -226,7 +345,7 @@ module axi_interconnect_wrapper # input wire [ARUSER_WIDTH-1:0] s03_axi_aruser, input wire s03_axi_arvalid, output wire s03_axi_arready, - output wire [ID_WIDTH-1:0] s03_axi_rid, + output wire [S_ID_WIDTH-1:0] s03_axi_rid, output wire [DATA_WIDTH-1:0] s03_axi_rdata, output wire [1:0] s03_axi_rresp, output wire s03_axi_rlast, @@ -237,7 +356,7 @@ module axi_interconnect_wrapper # /* * AXI master interface */ - output wire [ID_WIDTH-1:0] m00_axi_awid, + output wire [M_ID_WIDTH-1:0] m00_axi_awid, output wire [ADDR_WIDTH-1:0] m00_axi_awaddr, output wire [7:0] m00_axi_awlen, output wire [2:0] m00_axi_awsize, @@ -256,12 +375,12 @@ module axi_interconnect_wrapper # output wire [WUSER_WIDTH-1:0] m00_axi_wuser, output wire m00_axi_wvalid, input wire m00_axi_wready, - input wire [ID_WIDTH-1:0] m00_axi_bid, + input wire [M_ID_WIDTH-1:0] m00_axi_bid, input wire [1:0] m00_axi_bresp, input wire [BUSER_WIDTH-1:0] m00_axi_buser, input wire m00_axi_bvalid, output wire m00_axi_bready, - output wire [ID_WIDTH-1:0] m00_axi_arid, + output wire [M_ID_WIDTH-1:0] m00_axi_arid, output wire [ADDR_WIDTH-1:0] m00_axi_araddr, output wire [7:0] m00_axi_arlen, output wire [2:0] m00_axi_arsize, @@ -274,7 +393,7 @@ module axi_interconnect_wrapper # output wire [ARUSER_WIDTH-1:0] m00_axi_aruser, output wire m00_axi_arvalid, input wire m00_axi_arready, - input wire [ID_WIDTH-1:0] m00_axi_rid, + input wire [M_ID_WIDTH-1:0] m00_axi_rid, input wire [DATA_WIDTH-1:0] m00_axi_rdata, input wire [1:0] m00_axi_rresp, input wire m00_axi_rlast, @@ -299,17 +418,26 @@ function [S_COUNT-1:0] w_s(input [S_COUNT-1:0] val); w_s = val; endfunction +function [31:0] w_32(input [31:0] val); + w_32 = val; +endfunction + +function [1:0] w_2(input [1:0] val); + w_2 = val; +endfunction + function w_1(input val); w_1 = val; endfunction -axi_interconnect #( +axi_crossbar #( .S_COUNT(S_COUNT), .M_COUNT(M_COUNT), .DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH), .STRB_WIDTH(STRB_WIDTH), - .ID_WIDTH(ID_WIDTH), + .S_ID_WIDTH(S_ID_WIDTH), + .M_ID_WIDTH(M_ID_WIDTH), .AWUSER_ENABLE(AWUSER_ENABLE), .AWUSER_WIDTH(AWUSER_WIDTH), .WUSER_ENABLE(WUSER_ENABLE), @@ -320,15 +448,27 @@ axi_interconnect #( .ARUSER_WIDTH(ARUSER_WIDTH), .RUSER_ENABLE(RUSER_ENABLE), .RUSER_WIDTH(RUSER_WIDTH), - .FORWARD_ID(FORWARD_ID), + .S_THREADS({ w_32(S03_THREADS), w_32(S02_THREADS), w_32(S01_THREADS), w_32(S00_THREADS) }), + .S_ACCEPT({ w_32(S03_ACCEPT), w_32(S02_ACCEPT), w_32(S01_ACCEPT), w_32(S00_ACCEPT) }), .M_REGIONS(M_REGIONS), .M_BASE_ADDR({ w_a_r(M00_BASE_ADDR) }), .M_ADDR_WIDTH({ w_32_r(M00_ADDR_WIDTH) }), .M_CONNECT_READ({ w_s(M00_CONNECT_READ) }), .M_CONNECT_WRITE({ w_s(M00_CONNECT_WRITE) }), - .M_SECURE({ w_1(M00_SECURE) }) + .M_ISSUE({ w_32(M00_ISSUE) }), + .M_SECURE({ w_1(M00_SECURE) }), + .S_AR_REG_TYPE({ w_2(S03_AR_REG_TYPE), w_2(S02_AR_REG_TYPE), w_2(S01_AR_REG_TYPE), w_2(S00_AR_REG_TYPE) }), + .S_R_REG_TYPE({ w_2(S03_R_REG_TYPE), w_2(S02_R_REG_TYPE), w_2(S01_R_REG_TYPE), w_2(S00_R_REG_TYPE) }), + .S_AW_REG_TYPE({ w_2(S03_AW_REG_TYPE), w_2(S02_AW_REG_TYPE), w_2(S01_AW_REG_TYPE), w_2(S00_AW_REG_TYPE) }), + .S_W_REG_TYPE({ w_2(S03_W_REG_TYPE), w_2(S02_W_REG_TYPE), w_2(S01_W_REG_TYPE), w_2(S00_W_REG_TYPE) }), + .S_B_REG_TYPE({ w_2(S03_B_REG_TYPE), w_2(S02_B_REG_TYPE), w_2(S01_B_REG_TYPE), w_2(S00_B_REG_TYPE) }), + .M_AR_REG_TYPE({ w_2(M00_AR_REG_TYPE) }), + .M_R_REG_TYPE({ w_2(M00_R_REG_TYPE) }), + .M_AW_REG_TYPE({ w_2(M00_AW_REG_TYPE) }), + .M_W_REG_TYPE({ w_2(M00_W_REG_TYPE) }), + .M_B_REG_TYPE({ w_2(M00_B_REG_TYPE) }) ) -axi_interconnect_inst ( +axi_crossbar_inst ( .clk(clk), .rst(rst), .s_axi_awid({ s03_axi_awid, s02_axi_awid, s01_axi_awid, s00_axi_awid }), diff --git a/xls/modules/zstd/external/axi_register_rd.v b/xls/modules/zstd/external/axi_register_rd.v new file mode 100644 index 0000000000..c0df03a03f --- /dev/null +++ b/xls/modules/zstd/external/axi_register_rd.v @@ -0,0 +1,530 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 register (read) + */ +module axi_register_rd # +( + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Width of ID signal + parameter ID_WIDTH = 8, + // Propagate aruser signal + parameter ARUSER_ENABLE = 0, + // Width of aruser signal + parameter ARUSER_WIDTH = 1, + // Propagate ruser signal + parameter RUSER_ENABLE = 0, + // Width of ruser signal + parameter RUSER_WIDTH = 1, + // AR channel register type + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter AR_REG_TYPE = 1, + // R channel register type + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter R_REG_TYPE = 2 +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interface + */ + input wire [ID_WIDTH-1:0] s_axi_arid, + input wire [ADDR_WIDTH-1:0] s_axi_araddr, + input wire [7:0] s_axi_arlen, + input wire [2:0] s_axi_arsize, + input wire [1:0] s_axi_arburst, + input wire s_axi_arlock, + input wire [3:0] s_axi_arcache, + input wire [2:0] s_axi_arprot, + input wire [3:0] s_axi_arqos, + input wire [3:0] s_axi_arregion, + input wire [ARUSER_WIDTH-1:0] s_axi_aruser, + input wire s_axi_arvalid, + output wire s_axi_arready, + output wire [ID_WIDTH-1:0] s_axi_rid, + output wire [DATA_WIDTH-1:0] s_axi_rdata, + output wire [1:0] s_axi_rresp, + output wire s_axi_rlast, + output wire [RUSER_WIDTH-1:0] s_axi_ruser, + output wire s_axi_rvalid, + input wire s_axi_rready, + + /* + * AXI master interface + */ + output wire [ID_WIDTH-1:0] m_axi_arid, + output wire [ADDR_WIDTH-1:0] m_axi_araddr, + output wire [7:0] m_axi_arlen, + output wire [2:0] m_axi_arsize, + output wire [1:0] m_axi_arburst, + output wire m_axi_arlock, + output wire [3:0] m_axi_arcache, + output wire [2:0] m_axi_arprot, + output wire [3:0] m_axi_arqos, + output wire [3:0] m_axi_arregion, + output wire [ARUSER_WIDTH-1:0] m_axi_aruser, + output wire m_axi_arvalid, + input wire m_axi_arready, + input wire [ID_WIDTH-1:0] m_axi_rid, + input wire [DATA_WIDTH-1:0] m_axi_rdata, + input wire [1:0] m_axi_rresp, + input wire m_axi_rlast, + input wire [RUSER_WIDTH-1:0] m_axi_ruser, + input wire m_axi_rvalid, + output wire m_axi_rready +); + +generate + +// AR channel + +if (AR_REG_TYPE > 1) begin +// skid buffer, no bubble cycles + +// datapath registers +reg s_axi_arready_reg = 1'b0; + +reg [ID_WIDTH-1:0] m_axi_arid_reg = {ID_WIDTH{1'b0}}; +reg [ADDR_WIDTH-1:0] m_axi_araddr_reg = {ADDR_WIDTH{1'b0}}; +reg [7:0] m_axi_arlen_reg = 8'd0; +reg [2:0] m_axi_arsize_reg = 3'd0; +reg [1:0] m_axi_arburst_reg = 2'd0; +reg m_axi_arlock_reg = 1'b0; +reg [3:0] m_axi_arcache_reg = 4'd0; +reg [2:0] m_axi_arprot_reg = 3'd0; +reg [3:0] m_axi_arqos_reg = 4'd0; +reg [3:0] m_axi_arregion_reg = 4'd0; +reg [ARUSER_WIDTH-1:0] m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}}; +reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next; + +reg [ID_WIDTH-1:0] temp_m_axi_arid_reg = {ID_WIDTH{1'b0}}; +reg [ADDR_WIDTH-1:0] temp_m_axi_araddr_reg = {ADDR_WIDTH{1'b0}}; +reg [7:0] temp_m_axi_arlen_reg = 8'd0; +reg [2:0] temp_m_axi_arsize_reg = 3'd0; +reg [1:0] temp_m_axi_arburst_reg = 2'd0; +reg temp_m_axi_arlock_reg = 1'b0; +reg [3:0] temp_m_axi_arcache_reg = 4'd0; +reg [2:0] temp_m_axi_arprot_reg = 3'd0; +reg [3:0] temp_m_axi_arqos_reg = 4'd0; +reg [3:0] temp_m_axi_arregion_reg = 4'd0; +reg [ARUSER_WIDTH-1:0] temp_m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}}; +reg temp_m_axi_arvalid_reg = 1'b0, temp_m_axi_arvalid_next; + +// datapath control +reg store_axi_ar_input_to_output; +reg store_axi_ar_input_to_temp; +reg store_axi_ar_temp_to_output; + +assign s_axi_arready = s_axi_arready_reg; + +assign m_axi_arid = m_axi_arid_reg; +assign m_axi_araddr = m_axi_araddr_reg; +assign m_axi_arlen = m_axi_arlen_reg; +assign m_axi_arsize = m_axi_arsize_reg; +assign m_axi_arburst = m_axi_arburst_reg; +assign m_axi_arlock = m_axi_arlock_reg; +assign m_axi_arcache = m_axi_arcache_reg; +assign m_axi_arprot = m_axi_arprot_reg; +assign m_axi_arqos = m_axi_arqos_reg; +assign m_axi_arregion = m_axi_arregion_reg; +assign m_axi_aruser = ARUSER_ENABLE ? m_axi_aruser_reg : {ARUSER_WIDTH{1'b0}}; +assign m_axi_arvalid = m_axi_arvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +wire s_axi_arready_early = m_axi_arready | (~temp_m_axi_arvalid_reg & (~m_axi_arvalid_reg | ~s_axi_arvalid)); + +always @* begin + // transfer sink ready state to source + m_axi_arvalid_next = m_axi_arvalid_reg; + temp_m_axi_arvalid_next = temp_m_axi_arvalid_reg; + + store_axi_ar_input_to_output = 1'b0; + store_axi_ar_input_to_temp = 1'b0; + store_axi_ar_temp_to_output = 1'b0; + + if (s_axi_arready_reg) begin + // input is ready + if (m_axi_arready | ~m_axi_arvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axi_arvalid_next = s_axi_arvalid; + store_axi_ar_input_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axi_arvalid_next = s_axi_arvalid; + store_axi_ar_input_to_temp = 1'b1; + end + end else if (m_axi_arready) begin + // input is not ready, but output is ready + m_axi_arvalid_next = temp_m_axi_arvalid_reg; + temp_m_axi_arvalid_next = 1'b0; + store_axi_ar_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_arready_reg <= 1'b0; + m_axi_arvalid_reg <= 1'b0; + temp_m_axi_arvalid_reg <= 1'b0; + end else begin + s_axi_arready_reg <= s_axi_arready_early; + m_axi_arvalid_reg <= m_axi_arvalid_next; + temp_m_axi_arvalid_reg <= temp_m_axi_arvalid_next; + end + + // datapath + if (store_axi_ar_input_to_output) begin + m_axi_arid_reg <= s_axi_arid; + m_axi_araddr_reg <= s_axi_araddr; + m_axi_arlen_reg <= s_axi_arlen; + m_axi_arsize_reg <= s_axi_arsize; + m_axi_arburst_reg <= s_axi_arburst; + m_axi_arlock_reg <= s_axi_arlock; + m_axi_arcache_reg <= s_axi_arcache; + m_axi_arprot_reg <= s_axi_arprot; + m_axi_arqos_reg <= s_axi_arqos; + m_axi_arregion_reg <= s_axi_arregion; + m_axi_aruser_reg <= s_axi_aruser; + end else if (store_axi_ar_temp_to_output) begin + m_axi_arid_reg <= temp_m_axi_arid_reg; + m_axi_araddr_reg <= temp_m_axi_araddr_reg; + m_axi_arlen_reg <= temp_m_axi_arlen_reg; + m_axi_arsize_reg <= temp_m_axi_arsize_reg; + m_axi_arburst_reg <= temp_m_axi_arburst_reg; + m_axi_arlock_reg <= temp_m_axi_arlock_reg; + m_axi_arcache_reg <= temp_m_axi_arcache_reg; + m_axi_arprot_reg <= temp_m_axi_arprot_reg; + m_axi_arqos_reg <= temp_m_axi_arqos_reg; + m_axi_arregion_reg <= temp_m_axi_arregion_reg; + m_axi_aruser_reg <= temp_m_axi_aruser_reg; + end + + if (store_axi_ar_input_to_temp) begin + temp_m_axi_arid_reg <= s_axi_arid; + temp_m_axi_araddr_reg <= s_axi_araddr; + temp_m_axi_arlen_reg <= s_axi_arlen; + temp_m_axi_arsize_reg <= s_axi_arsize; + temp_m_axi_arburst_reg <= s_axi_arburst; + temp_m_axi_arlock_reg <= s_axi_arlock; + temp_m_axi_arcache_reg <= s_axi_arcache; + temp_m_axi_arprot_reg <= s_axi_arprot; + temp_m_axi_arqos_reg <= s_axi_arqos; + temp_m_axi_arregion_reg <= s_axi_arregion; + temp_m_axi_aruser_reg <= s_axi_aruser; + end +end + +end else if (AR_REG_TYPE == 1) begin +// simple register, inserts bubble cycles + +// datapath registers +reg s_axi_arready_reg = 1'b0; + +reg [ID_WIDTH-1:0] m_axi_arid_reg = {ID_WIDTH{1'b0}}; +reg [ADDR_WIDTH-1:0] m_axi_araddr_reg = {ADDR_WIDTH{1'b0}}; +reg [7:0] m_axi_arlen_reg = 8'd0; +reg [2:0] m_axi_arsize_reg = 3'd0; +reg [1:0] m_axi_arburst_reg = 2'd0; +reg m_axi_arlock_reg = 1'b0; +reg [3:0] m_axi_arcache_reg = 4'd0; +reg [2:0] m_axi_arprot_reg = 3'd0; +reg [3:0] m_axi_arqos_reg = 4'd0; +reg [3:0] m_axi_arregion_reg = 4'd0; +reg [ARUSER_WIDTH-1:0] m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}}; +reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next; + +// datapath control +reg store_axi_ar_input_to_output; + +assign s_axi_arready = s_axi_arready_reg; + +assign m_axi_arid = m_axi_arid_reg; +assign m_axi_araddr = m_axi_araddr_reg; +assign m_axi_arlen = m_axi_arlen_reg; +assign m_axi_arsize = m_axi_arsize_reg; +assign m_axi_arburst = m_axi_arburst_reg; +assign m_axi_arlock = m_axi_arlock_reg; +assign m_axi_arcache = m_axi_arcache_reg; +assign m_axi_arprot = m_axi_arprot_reg; +assign m_axi_arqos = m_axi_arqos_reg; +assign m_axi_arregion = m_axi_arregion_reg; +assign m_axi_aruser = ARUSER_ENABLE ? m_axi_aruser_reg : {ARUSER_WIDTH{1'b0}}; +assign m_axi_arvalid = m_axi_arvalid_reg; + +// enable ready input next cycle if output buffer will be empty +wire s_axi_arready_early = !m_axi_arvalid_next; + +always @* begin + // transfer sink ready state to source + m_axi_arvalid_next = m_axi_arvalid_reg; + + store_axi_ar_input_to_output = 1'b0; + + if (s_axi_arready_reg) begin + m_axi_arvalid_next = s_axi_arvalid; + store_axi_ar_input_to_output = 1'b1; + end else if (m_axi_arready) begin + m_axi_arvalid_next = 1'b0; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_arready_reg <= 1'b0; + m_axi_arvalid_reg <= 1'b0; + end else begin + s_axi_arready_reg <= s_axi_arready_early; + m_axi_arvalid_reg <= m_axi_arvalid_next; + end + + // datapath + if (store_axi_ar_input_to_output) begin + m_axi_arid_reg <= s_axi_arid; + m_axi_araddr_reg <= s_axi_araddr; + m_axi_arlen_reg <= s_axi_arlen; + m_axi_arsize_reg <= s_axi_arsize; + m_axi_arburst_reg <= s_axi_arburst; + m_axi_arlock_reg <= s_axi_arlock; + m_axi_arcache_reg <= s_axi_arcache; + m_axi_arprot_reg <= s_axi_arprot; + m_axi_arqos_reg <= s_axi_arqos; + m_axi_arregion_reg <= s_axi_arregion; + m_axi_aruser_reg <= s_axi_aruser; + end +end + +end else begin + + // bypass AR channel + assign m_axi_arid = s_axi_arid; + assign m_axi_araddr = s_axi_araddr; + assign m_axi_arlen = s_axi_arlen; + assign m_axi_arsize = s_axi_arsize; + assign m_axi_arburst = s_axi_arburst; + assign m_axi_arlock = s_axi_arlock; + assign m_axi_arcache = s_axi_arcache; + assign m_axi_arprot = s_axi_arprot; + assign m_axi_arqos = s_axi_arqos; + assign m_axi_arregion = s_axi_arregion; + assign m_axi_aruser = ARUSER_ENABLE ? s_axi_aruser : {ARUSER_WIDTH{1'b0}}; + assign m_axi_arvalid = s_axi_arvalid; + assign s_axi_arready = m_axi_arready; + +end + +// R channel + +if (R_REG_TYPE > 1) begin +// skid buffer, no bubble cycles + +// datapath registers +reg m_axi_rready_reg = 1'b0; + +reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; +reg [1:0] s_axi_rresp_reg = 2'b0; +reg s_axi_rlast_reg = 1'b0; +reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = {RUSER_WIDTH{1'b0}}; +reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next; + +reg [ID_WIDTH-1:0] temp_s_axi_rid_reg = {ID_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] temp_s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; +reg [1:0] temp_s_axi_rresp_reg = 2'b0; +reg temp_s_axi_rlast_reg = 1'b0; +reg [RUSER_WIDTH-1:0] temp_s_axi_ruser_reg = {RUSER_WIDTH{1'b0}}; +reg temp_s_axi_rvalid_reg = 1'b0, temp_s_axi_rvalid_next; + +// datapath control +reg store_axi_r_input_to_output; +reg store_axi_r_input_to_temp; +reg store_axi_r_temp_to_output; + +assign m_axi_rready = m_axi_rready_reg; + +assign s_axi_rid = s_axi_rid_reg; +assign s_axi_rdata = s_axi_rdata_reg; +assign s_axi_rresp = s_axi_rresp_reg; +assign s_axi_rlast = s_axi_rlast_reg; +assign s_axi_ruser = RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}}; +assign s_axi_rvalid = s_axi_rvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +wire m_axi_rready_early = s_axi_rready | (~temp_s_axi_rvalid_reg & (~s_axi_rvalid_reg | ~m_axi_rvalid)); + +always @* begin + // transfer sink ready state to source + s_axi_rvalid_next = s_axi_rvalid_reg; + temp_s_axi_rvalid_next = temp_s_axi_rvalid_reg; + + store_axi_r_input_to_output = 1'b0; + store_axi_r_input_to_temp = 1'b0; + store_axi_r_temp_to_output = 1'b0; + + if (m_axi_rready_reg) begin + // input is ready + if (s_axi_rready | ~s_axi_rvalid_reg) begin + // output is ready or currently not valid, transfer data to output + s_axi_rvalid_next = m_axi_rvalid; + store_axi_r_input_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_s_axi_rvalid_next = m_axi_rvalid; + store_axi_r_input_to_temp = 1'b1; + end + end else if (s_axi_rready) begin + // input is not ready, but output is ready + s_axi_rvalid_next = temp_s_axi_rvalid_reg; + temp_s_axi_rvalid_next = 1'b0; + store_axi_r_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + m_axi_rready_reg <= 1'b0; + s_axi_rvalid_reg <= 1'b0; + temp_s_axi_rvalid_reg <= 1'b0; + end else begin + m_axi_rready_reg <= m_axi_rready_early; + s_axi_rvalid_reg <= s_axi_rvalid_next; + temp_s_axi_rvalid_reg <= temp_s_axi_rvalid_next; + end + + // datapath + if (store_axi_r_input_to_output) begin + s_axi_rid_reg <= m_axi_rid; + s_axi_rdata_reg <= m_axi_rdata; + s_axi_rresp_reg <= m_axi_rresp; + s_axi_rlast_reg <= m_axi_rlast; + s_axi_ruser_reg <= m_axi_ruser; + end else if (store_axi_r_temp_to_output) begin + s_axi_rid_reg <= temp_s_axi_rid_reg; + s_axi_rdata_reg <= temp_s_axi_rdata_reg; + s_axi_rresp_reg <= temp_s_axi_rresp_reg; + s_axi_rlast_reg <= temp_s_axi_rlast_reg; + s_axi_ruser_reg <= temp_s_axi_ruser_reg; + end + + if (store_axi_r_input_to_temp) begin + temp_s_axi_rid_reg <= m_axi_rid; + temp_s_axi_rdata_reg <= m_axi_rdata; + temp_s_axi_rresp_reg <= m_axi_rresp; + temp_s_axi_rlast_reg <= m_axi_rlast; + temp_s_axi_ruser_reg <= m_axi_ruser; + end +end + +end else if (R_REG_TYPE == 1) begin +// simple register, inserts bubble cycles + +// datapath registers +reg m_axi_rready_reg = 1'b0; + +reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; +reg [1:0] s_axi_rresp_reg = 2'b0; +reg s_axi_rlast_reg = 1'b0; +reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = {RUSER_WIDTH{1'b0}}; +reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next; + +// datapath control +reg store_axi_r_input_to_output; + +assign m_axi_rready = m_axi_rready_reg; + +assign s_axi_rid = s_axi_rid_reg; +assign s_axi_rdata = s_axi_rdata_reg; +assign s_axi_rresp = s_axi_rresp_reg; +assign s_axi_rlast = s_axi_rlast_reg; +assign s_axi_ruser = RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}}; +assign s_axi_rvalid = s_axi_rvalid_reg; + +// enable ready input next cycle if output buffer will be empty +wire m_axi_rready_early = !s_axi_rvalid_next; + +always @* begin + // transfer sink ready state to source + s_axi_rvalid_next = s_axi_rvalid_reg; + + store_axi_r_input_to_output = 1'b0; + + if (m_axi_rready_reg) begin + s_axi_rvalid_next = m_axi_rvalid; + store_axi_r_input_to_output = 1'b1; + end else if (s_axi_rready) begin + s_axi_rvalid_next = 1'b0; + end +end + +always @(posedge clk) begin + if (rst) begin + m_axi_rready_reg <= 1'b0; + s_axi_rvalid_reg <= 1'b0; + end else begin + m_axi_rready_reg <= m_axi_rready_early; + s_axi_rvalid_reg <= s_axi_rvalid_next; + end + + // datapath + if (store_axi_r_input_to_output) begin + s_axi_rid_reg <= m_axi_rid; + s_axi_rdata_reg <= m_axi_rdata; + s_axi_rresp_reg <= m_axi_rresp; + s_axi_rlast_reg <= m_axi_rlast; + s_axi_ruser_reg <= m_axi_ruser; + end +end + +end else begin + + // bypass R channel + assign s_axi_rid = m_axi_rid; + assign s_axi_rdata = m_axi_rdata; + assign s_axi_rresp = m_axi_rresp; + assign s_axi_rlast = m_axi_rlast; + assign s_axi_ruser = RUSER_ENABLE ? m_axi_ruser : {RUSER_WIDTH{1'b0}}; + assign s_axi_rvalid = m_axi_rvalid; + assign m_axi_rready = s_axi_rready; + +end + +endgenerate + +endmodule + +`resetall diff --git a/xls/modules/zstd/external/axi_register_wr.v b/xls/modules/zstd/external/axi_register_wr.v new file mode 100644 index 0000000000..9176d6ba95 --- /dev/null +++ b/xls/modules/zstd/external/axi_register_wr.v @@ -0,0 +1,691 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 register (write) + */ +module axi_register_wr # +( + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Width of ID signal + parameter ID_WIDTH = 8, + // Propagate awuser signal + parameter AWUSER_ENABLE = 0, + // Width of awuser signal + parameter AWUSER_WIDTH = 1, + // Propagate wuser signal + parameter WUSER_ENABLE = 0, + // Width of wuser signal + parameter WUSER_WIDTH = 1, + // Propagate buser signal + parameter BUSER_ENABLE = 0, + // Width of buser signal + parameter BUSER_WIDTH = 1, + // AW channel register type + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter AW_REG_TYPE = 1, + // W channel register type + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter W_REG_TYPE = 2, + // B channel register type + // 0 to bypass, 1 for simple buffer, 2 for skid buffer + parameter B_REG_TYPE = 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI slave interface + */ + input wire [ID_WIDTH-1:0] s_axi_awid, + input wire [ADDR_WIDTH-1:0] s_axi_awaddr, + input wire [7:0] s_axi_awlen, + input wire [2:0] s_axi_awsize, + input wire [1:0] s_axi_awburst, + input wire s_axi_awlock, + input wire [3:0] s_axi_awcache, + input wire [2:0] s_axi_awprot, + input wire [3:0] s_axi_awqos, + input wire [3:0] s_axi_awregion, + input wire [AWUSER_WIDTH-1:0] s_axi_awuser, + input wire s_axi_awvalid, + output wire s_axi_awready, + input wire [DATA_WIDTH-1:0] s_axi_wdata, + input wire [STRB_WIDTH-1:0] s_axi_wstrb, + input wire s_axi_wlast, + input wire [WUSER_WIDTH-1:0] s_axi_wuser, + input wire s_axi_wvalid, + output wire s_axi_wready, + output wire [ID_WIDTH-1:0] s_axi_bid, + output wire [1:0] s_axi_bresp, + output wire [BUSER_WIDTH-1:0] s_axi_buser, + output wire s_axi_bvalid, + input wire s_axi_bready, + + /* + * AXI master interface + */ + output wire [ID_WIDTH-1:0] m_axi_awid, + output wire [ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [7:0] m_axi_awlen, + output wire [2:0] m_axi_awsize, + output wire [1:0] m_axi_awburst, + output wire m_axi_awlock, + output wire [3:0] m_axi_awcache, + output wire [2:0] m_axi_awprot, + output wire [3:0] m_axi_awqos, + output wire [3:0] m_axi_awregion, + output wire [AWUSER_WIDTH-1:0] m_axi_awuser, + output wire m_axi_awvalid, + input wire m_axi_awready, + output wire [DATA_WIDTH-1:0] m_axi_wdata, + output wire [STRB_WIDTH-1:0] m_axi_wstrb, + output wire m_axi_wlast, + output wire [WUSER_WIDTH-1:0] m_axi_wuser, + output wire m_axi_wvalid, + input wire m_axi_wready, + input wire [ID_WIDTH-1:0] m_axi_bid, + input wire [1:0] m_axi_bresp, + input wire [BUSER_WIDTH-1:0] m_axi_buser, + input wire m_axi_bvalid, + output wire m_axi_bready +); + +generate + +// AW channel + +if (AW_REG_TYPE > 1) begin +// skid buffer, no bubble cycles + +// datapath registers +reg s_axi_awready_reg = 1'b0; + +reg [ID_WIDTH-1:0] m_axi_awid_reg = {ID_WIDTH{1'b0}}; +reg [ADDR_WIDTH-1:0] m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}}; +reg [7:0] m_axi_awlen_reg = 8'd0; +reg [2:0] m_axi_awsize_reg = 3'd0; +reg [1:0] m_axi_awburst_reg = 2'd0; +reg m_axi_awlock_reg = 1'b0; +reg [3:0] m_axi_awcache_reg = 4'd0; +reg [2:0] m_axi_awprot_reg = 3'd0; +reg [3:0] m_axi_awqos_reg = 4'd0; +reg [3:0] m_axi_awregion_reg = 4'd0; +reg [AWUSER_WIDTH-1:0] m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}}; +reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next; + +reg [ID_WIDTH-1:0] temp_m_axi_awid_reg = {ID_WIDTH{1'b0}}; +reg [ADDR_WIDTH-1:0] temp_m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}}; +reg [7:0] temp_m_axi_awlen_reg = 8'd0; +reg [2:0] temp_m_axi_awsize_reg = 3'd0; +reg [1:0] temp_m_axi_awburst_reg = 2'd0; +reg temp_m_axi_awlock_reg = 1'b0; +reg [3:0] temp_m_axi_awcache_reg = 4'd0; +reg [2:0] temp_m_axi_awprot_reg = 3'd0; +reg [3:0] temp_m_axi_awqos_reg = 4'd0; +reg [3:0] temp_m_axi_awregion_reg = 4'd0; +reg [AWUSER_WIDTH-1:0] temp_m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}}; +reg temp_m_axi_awvalid_reg = 1'b0, temp_m_axi_awvalid_next; + +// datapath control +reg store_axi_aw_input_to_output; +reg store_axi_aw_input_to_temp; +reg store_axi_aw_temp_to_output; + +assign s_axi_awready = s_axi_awready_reg; + +assign m_axi_awid = m_axi_awid_reg; +assign m_axi_awaddr = m_axi_awaddr_reg; +assign m_axi_awlen = m_axi_awlen_reg; +assign m_axi_awsize = m_axi_awsize_reg; +assign m_axi_awburst = m_axi_awburst_reg; +assign m_axi_awlock = m_axi_awlock_reg; +assign m_axi_awcache = m_axi_awcache_reg; +assign m_axi_awprot = m_axi_awprot_reg; +assign m_axi_awqos = m_axi_awqos_reg; +assign m_axi_awregion = m_axi_awregion_reg; +assign m_axi_awuser = AWUSER_ENABLE ? m_axi_awuser_reg : {AWUSER_WIDTH{1'b0}}; +assign m_axi_awvalid = m_axi_awvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +wire s_axi_awready_early = m_axi_awready | (~temp_m_axi_awvalid_reg & (~m_axi_awvalid_reg | ~s_axi_awvalid)); + +always @* begin + // transfer sink ready state to source + m_axi_awvalid_next = m_axi_awvalid_reg; + temp_m_axi_awvalid_next = temp_m_axi_awvalid_reg; + + store_axi_aw_input_to_output = 1'b0; + store_axi_aw_input_to_temp = 1'b0; + store_axi_aw_temp_to_output = 1'b0; + + if (s_axi_awready_reg) begin + // input is ready + if (m_axi_awready | ~m_axi_awvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axi_awvalid_next = s_axi_awvalid; + store_axi_aw_input_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axi_awvalid_next = s_axi_awvalid; + store_axi_aw_input_to_temp = 1'b1; + end + end else if (m_axi_awready) begin + // input is not ready, but output is ready + m_axi_awvalid_next = temp_m_axi_awvalid_reg; + temp_m_axi_awvalid_next = 1'b0; + store_axi_aw_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_awready_reg <= 1'b0; + m_axi_awvalid_reg <= 1'b0; + temp_m_axi_awvalid_reg <= 1'b0; + end else begin + s_axi_awready_reg <= s_axi_awready_early; + m_axi_awvalid_reg <= m_axi_awvalid_next; + temp_m_axi_awvalid_reg <= temp_m_axi_awvalid_next; + end + + // datapath + if (store_axi_aw_input_to_output) begin + m_axi_awid_reg <= s_axi_awid; + m_axi_awaddr_reg <= s_axi_awaddr; + m_axi_awlen_reg <= s_axi_awlen; + m_axi_awsize_reg <= s_axi_awsize; + m_axi_awburst_reg <= s_axi_awburst; + m_axi_awlock_reg <= s_axi_awlock; + m_axi_awcache_reg <= s_axi_awcache; + m_axi_awprot_reg <= s_axi_awprot; + m_axi_awqos_reg <= s_axi_awqos; + m_axi_awregion_reg <= s_axi_awregion; + m_axi_awuser_reg <= s_axi_awuser; + end else if (store_axi_aw_temp_to_output) begin + m_axi_awid_reg <= temp_m_axi_awid_reg; + m_axi_awaddr_reg <= temp_m_axi_awaddr_reg; + m_axi_awlen_reg <= temp_m_axi_awlen_reg; + m_axi_awsize_reg <= temp_m_axi_awsize_reg; + m_axi_awburst_reg <= temp_m_axi_awburst_reg; + m_axi_awlock_reg <= temp_m_axi_awlock_reg; + m_axi_awcache_reg <= temp_m_axi_awcache_reg; + m_axi_awprot_reg <= temp_m_axi_awprot_reg; + m_axi_awqos_reg <= temp_m_axi_awqos_reg; + m_axi_awregion_reg <= temp_m_axi_awregion_reg; + m_axi_awuser_reg <= temp_m_axi_awuser_reg; + end + + if (store_axi_aw_input_to_temp) begin + temp_m_axi_awid_reg <= s_axi_awid; + temp_m_axi_awaddr_reg <= s_axi_awaddr; + temp_m_axi_awlen_reg <= s_axi_awlen; + temp_m_axi_awsize_reg <= s_axi_awsize; + temp_m_axi_awburst_reg <= s_axi_awburst; + temp_m_axi_awlock_reg <= s_axi_awlock; + temp_m_axi_awcache_reg <= s_axi_awcache; + temp_m_axi_awprot_reg <= s_axi_awprot; + temp_m_axi_awqos_reg <= s_axi_awqos; + temp_m_axi_awregion_reg <= s_axi_awregion; + temp_m_axi_awuser_reg <= s_axi_awuser; + end +end + +end else if (AW_REG_TYPE == 1) begin +// simple register, inserts bubble cycles + +// datapath registers +reg s_axi_awready_reg = 1'b0; + +reg [ID_WIDTH-1:0] m_axi_awid_reg = {ID_WIDTH{1'b0}}; +reg [ADDR_WIDTH-1:0] m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}}; +reg [7:0] m_axi_awlen_reg = 8'd0; +reg [2:0] m_axi_awsize_reg = 3'd0; +reg [1:0] m_axi_awburst_reg = 2'd0; +reg m_axi_awlock_reg = 1'b0; +reg [3:0] m_axi_awcache_reg = 4'd0; +reg [2:0] m_axi_awprot_reg = 3'd0; +reg [3:0] m_axi_awqos_reg = 4'd0; +reg [3:0] m_axi_awregion_reg = 4'd0; +reg [AWUSER_WIDTH-1:0] m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}}; +reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next; + +// datapath control +reg store_axi_aw_input_to_output; + +assign s_axi_awready = s_axi_awready_reg; + +assign m_axi_awid = m_axi_awid_reg; +assign m_axi_awaddr = m_axi_awaddr_reg; +assign m_axi_awlen = m_axi_awlen_reg; +assign m_axi_awsize = m_axi_awsize_reg; +assign m_axi_awburst = m_axi_awburst_reg; +assign m_axi_awlock = m_axi_awlock_reg; +assign m_axi_awcache = m_axi_awcache_reg; +assign m_axi_awprot = m_axi_awprot_reg; +assign m_axi_awqos = m_axi_awqos_reg; +assign m_axi_awregion = m_axi_awregion_reg; +assign m_axi_awuser = AWUSER_ENABLE ? m_axi_awuser_reg : {AWUSER_WIDTH{1'b0}}; +assign m_axi_awvalid = m_axi_awvalid_reg; + +// enable ready input next cycle if output buffer will be empty +wire s_axi_awready_eawly = !m_axi_awvalid_next; + +always @* begin + // transfer sink ready state to source + m_axi_awvalid_next = m_axi_awvalid_reg; + + store_axi_aw_input_to_output = 1'b0; + + if (s_axi_awready_reg) begin + m_axi_awvalid_next = s_axi_awvalid; + store_axi_aw_input_to_output = 1'b1; + end else if (m_axi_awready) begin + m_axi_awvalid_next = 1'b0; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_awready_reg <= 1'b0; + m_axi_awvalid_reg <= 1'b0; + end else begin + s_axi_awready_reg <= s_axi_awready_eawly; + m_axi_awvalid_reg <= m_axi_awvalid_next; + end + + // datapath + if (store_axi_aw_input_to_output) begin + m_axi_awid_reg <= s_axi_awid; + m_axi_awaddr_reg <= s_axi_awaddr; + m_axi_awlen_reg <= s_axi_awlen; + m_axi_awsize_reg <= s_axi_awsize; + m_axi_awburst_reg <= s_axi_awburst; + m_axi_awlock_reg <= s_axi_awlock; + m_axi_awcache_reg <= s_axi_awcache; + m_axi_awprot_reg <= s_axi_awprot; + m_axi_awqos_reg <= s_axi_awqos; + m_axi_awregion_reg <= s_axi_awregion; + m_axi_awuser_reg <= s_axi_awuser; + end +end + +end else begin + + // bypass AW channel + assign m_axi_awid = s_axi_awid; + assign m_axi_awaddr = s_axi_awaddr; + assign m_axi_awlen = s_axi_awlen; + assign m_axi_awsize = s_axi_awsize; + assign m_axi_awburst = s_axi_awburst; + assign m_axi_awlock = s_axi_awlock; + assign m_axi_awcache = s_axi_awcache; + assign m_axi_awprot = s_axi_awprot; + assign m_axi_awqos = s_axi_awqos; + assign m_axi_awregion = s_axi_awregion; + assign m_axi_awuser = AWUSER_ENABLE ? s_axi_awuser : {AWUSER_WIDTH{1'b0}}; + assign m_axi_awvalid = s_axi_awvalid; + assign s_axi_awready = m_axi_awready; + +end + +// W channel + +if (W_REG_TYPE > 1) begin +// skid buffer, no bubble cycles + +// datapath registers +reg s_axi_wready_reg = 1'b0; + +reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; +reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; +reg m_axi_wlast_reg = 1'b0; +reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = {WUSER_WIDTH{1'b0}}; +reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next; + +reg [DATA_WIDTH-1:0] temp_m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; +reg [STRB_WIDTH-1:0] temp_m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; +reg temp_m_axi_wlast_reg = 1'b0; +reg [WUSER_WIDTH-1:0] temp_m_axi_wuser_reg = {WUSER_WIDTH{1'b0}}; +reg temp_m_axi_wvalid_reg = 1'b0, temp_m_axi_wvalid_next; + +// datapath control +reg store_axi_w_input_to_output; +reg store_axi_w_input_to_temp; +reg store_axi_w_temp_to_output; + +assign s_axi_wready = s_axi_wready_reg; + +assign m_axi_wdata = m_axi_wdata_reg; +assign m_axi_wstrb = m_axi_wstrb_reg; +assign m_axi_wlast = m_axi_wlast_reg; +assign m_axi_wuser = WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}}; +assign m_axi_wvalid = m_axi_wvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +wire s_axi_wready_early = m_axi_wready | (~temp_m_axi_wvalid_reg & (~m_axi_wvalid_reg | ~s_axi_wvalid)); + +always @* begin + // transfer sink ready state to source + m_axi_wvalid_next = m_axi_wvalid_reg; + temp_m_axi_wvalid_next = temp_m_axi_wvalid_reg; + + store_axi_w_input_to_output = 1'b0; + store_axi_w_input_to_temp = 1'b0; + store_axi_w_temp_to_output = 1'b0; + + if (s_axi_wready_reg) begin + // input is ready + if (m_axi_wready | ~m_axi_wvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axi_wvalid_next = s_axi_wvalid; + store_axi_w_input_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axi_wvalid_next = s_axi_wvalid; + store_axi_w_input_to_temp = 1'b1; + end + end else if (m_axi_wready) begin + // input is not ready, but output is ready + m_axi_wvalid_next = temp_m_axi_wvalid_reg; + temp_m_axi_wvalid_next = 1'b0; + store_axi_w_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_wready_reg <= 1'b0; + m_axi_wvalid_reg <= 1'b0; + temp_m_axi_wvalid_reg <= 1'b0; + end else begin + s_axi_wready_reg <= s_axi_wready_early; + m_axi_wvalid_reg <= m_axi_wvalid_next; + temp_m_axi_wvalid_reg <= temp_m_axi_wvalid_next; + end + + // datapath + if (store_axi_w_input_to_output) begin + m_axi_wdata_reg <= s_axi_wdata; + m_axi_wstrb_reg <= s_axi_wstrb; + m_axi_wlast_reg <= s_axi_wlast; + m_axi_wuser_reg <= s_axi_wuser; + end else if (store_axi_w_temp_to_output) begin + m_axi_wdata_reg <= temp_m_axi_wdata_reg; + m_axi_wstrb_reg <= temp_m_axi_wstrb_reg; + m_axi_wlast_reg <= temp_m_axi_wlast_reg; + m_axi_wuser_reg <= temp_m_axi_wuser_reg; + end + + if (store_axi_w_input_to_temp) begin + temp_m_axi_wdata_reg <= s_axi_wdata; + temp_m_axi_wstrb_reg <= s_axi_wstrb; + temp_m_axi_wlast_reg <= s_axi_wlast; + temp_m_axi_wuser_reg <= s_axi_wuser; + end +end + +end else if (W_REG_TYPE == 1) begin +// simple register, inserts bubble cycles + +// datapath registers +reg s_axi_wready_reg = 1'b0; + +reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; +reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; +reg m_axi_wlast_reg = 1'b0; +reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = {WUSER_WIDTH{1'b0}}; +reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next; + +// datapath control +reg store_axi_w_input_to_output; + +assign s_axi_wready = s_axi_wready_reg; + +assign m_axi_wdata = m_axi_wdata_reg; +assign m_axi_wstrb = m_axi_wstrb_reg; +assign m_axi_wlast = m_axi_wlast_reg; +assign m_axi_wuser = WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}}; +assign m_axi_wvalid = m_axi_wvalid_reg; + +// enable ready input next cycle if output buffer will be empty +wire s_axi_wready_ewly = !m_axi_wvalid_next; + +always @* begin + // transfer sink ready state to source + m_axi_wvalid_next = m_axi_wvalid_reg; + + store_axi_w_input_to_output = 1'b0; + + if (s_axi_wready_reg) begin + m_axi_wvalid_next = s_axi_wvalid; + store_axi_w_input_to_output = 1'b1; + end else if (m_axi_wready) begin + m_axi_wvalid_next = 1'b0; + end +end + +always @(posedge clk) begin + if (rst) begin + s_axi_wready_reg <= 1'b0; + m_axi_wvalid_reg <= 1'b0; + end else begin + s_axi_wready_reg <= s_axi_wready_ewly; + m_axi_wvalid_reg <= m_axi_wvalid_next; + end + + // datapath + if (store_axi_w_input_to_output) begin + m_axi_wdata_reg <= s_axi_wdata; + m_axi_wstrb_reg <= s_axi_wstrb; + m_axi_wlast_reg <= s_axi_wlast; + m_axi_wuser_reg <= s_axi_wuser; + end +end + +end else begin + + // bypass W channel + assign m_axi_wdata = s_axi_wdata; + assign m_axi_wstrb = s_axi_wstrb; + assign m_axi_wlast = s_axi_wlast; + assign m_axi_wuser = WUSER_ENABLE ? s_axi_wuser : {WUSER_WIDTH{1'b0}}; + assign m_axi_wvalid = s_axi_wvalid; + assign s_axi_wready = m_axi_wready; + +end + +// B channel + +if (B_REG_TYPE > 1) begin +// skid buffer, no bubble cycles + +// datapath registers +reg m_axi_bready_reg = 1'b0; + +reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}; +reg [1:0] s_axi_bresp_reg = 2'b0; +reg [BUSER_WIDTH-1:0] s_axi_buser_reg = {BUSER_WIDTH{1'b0}}; +reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next; + +reg [ID_WIDTH-1:0] temp_s_axi_bid_reg = {ID_WIDTH{1'b0}}; +reg [1:0] temp_s_axi_bresp_reg = 2'b0; +reg [BUSER_WIDTH-1:0] temp_s_axi_buser_reg = {BUSER_WIDTH{1'b0}}; +reg temp_s_axi_bvalid_reg = 1'b0, temp_s_axi_bvalid_next; + +// datapath control +reg store_axi_b_input_to_output; +reg store_axi_b_input_to_temp; +reg store_axi_b_temp_to_output; + +assign m_axi_bready = m_axi_bready_reg; + +assign s_axi_bid = s_axi_bid_reg; +assign s_axi_bresp = s_axi_bresp_reg; +assign s_axi_buser = BUSER_ENABLE ? s_axi_buser_reg : {BUSER_WIDTH{1'b0}}; +assign s_axi_bvalid = s_axi_bvalid_reg; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +wire m_axi_bready_early = s_axi_bready | (~temp_s_axi_bvalid_reg & (~s_axi_bvalid_reg | ~m_axi_bvalid)); + +always @* begin + // transfer sink ready state to source + s_axi_bvalid_next = s_axi_bvalid_reg; + temp_s_axi_bvalid_next = temp_s_axi_bvalid_reg; + + store_axi_b_input_to_output = 1'b0; + store_axi_b_input_to_temp = 1'b0; + store_axi_b_temp_to_output = 1'b0; + + if (m_axi_bready_reg) begin + // input is ready + if (s_axi_bready | ~s_axi_bvalid_reg) begin + // output is ready or currently not valid, transfer data to output + s_axi_bvalid_next = m_axi_bvalid; + store_axi_b_input_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_s_axi_bvalid_next = m_axi_bvalid; + store_axi_b_input_to_temp = 1'b1; + end + end else if (s_axi_bready) begin + // input is not ready, but output is ready + s_axi_bvalid_next = temp_s_axi_bvalid_reg; + temp_s_axi_bvalid_next = 1'b0; + store_axi_b_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + if (rst) begin + m_axi_bready_reg <= 1'b0; + s_axi_bvalid_reg <= 1'b0; + temp_s_axi_bvalid_reg <= 1'b0; + end else begin + m_axi_bready_reg <= m_axi_bready_early; + s_axi_bvalid_reg <= s_axi_bvalid_next; + temp_s_axi_bvalid_reg <= temp_s_axi_bvalid_next; + end + + // datapath + if (store_axi_b_input_to_output) begin + s_axi_bid_reg <= m_axi_bid; + s_axi_bresp_reg <= m_axi_bresp; + s_axi_buser_reg <= m_axi_buser; + end else if (store_axi_b_temp_to_output) begin + s_axi_bid_reg <= temp_s_axi_bid_reg; + s_axi_bresp_reg <= temp_s_axi_bresp_reg; + s_axi_buser_reg <= temp_s_axi_buser_reg; + end + + if (store_axi_b_input_to_temp) begin + temp_s_axi_bid_reg <= m_axi_bid; + temp_s_axi_bresp_reg <= m_axi_bresp; + temp_s_axi_buser_reg <= m_axi_buser; + end +end + +end else if (B_REG_TYPE == 1) begin +// simple register, inserts bubble cycles + +// datapath registers +reg m_axi_bready_reg = 1'b0; + +reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}; +reg [1:0] s_axi_bresp_reg = 2'b0; +reg [BUSER_WIDTH-1:0] s_axi_buser_reg = {BUSER_WIDTH{1'b0}}; +reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next; + +// datapath control +reg store_axi_b_input_to_output; + +assign m_axi_bready = m_axi_bready_reg; + +assign s_axi_bid = s_axi_bid_reg; +assign s_axi_bresp = s_axi_bresp_reg; +assign s_axi_buser = BUSER_ENABLE ? s_axi_buser_reg : {BUSER_WIDTH{1'b0}}; +assign s_axi_bvalid = s_axi_bvalid_reg; + +// enable ready input next cycle if output buffer will be empty +wire m_axi_bready_early = !s_axi_bvalid_next; + +always @* begin + // transfer sink ready state to source + s_axi_bvalid_next = s_axi_bvalid_reg; + + store_axi_b_input_to_output = 1'b0; + + if (m_axi_bready_reg) begin + s_axi_bvalid_next = m_axi_bvalid; + store_axi_b_input_to_output = 1'b1; + end else if (s_axi_bready) begin + s_axi_bvalid_next = 1'b0; + end +end + +always @(posedge clk) begin + if (rst) begin + m_axi_bready_reg <= 1'b0; + s_axi_bvalid_reg <= 1'b0; + end else begin + m_axi_bready_reg <= m_axi_bready_early; + s_axi_bvalid_reg <= s_axi_bvalid_next; + end + + // datapath + if (store_axi_b_input_to_output) begin + s_axi_bid_reg <= m_axi_bid; + s_axi_bresp_reg <= m_axi_bresp; + s_axi_buser_reg <= m_axi_buser; + end +end + +end else begin + + // bypass B channel + assign s_axi_bid = m_axi_bid; + assign s_axi_bresp = m_axi_bresp; + assign s_axi_buser = BUSER_ENABLE ? m_axi_buser : {BUSER_WIDTH{1'b0}}; + assign s_axi_bvalid = m_axi_bvalid; + assign m_axi_bready = s_axi_bready; + +end + +endgenerate + +endmodule + +`resetall diff --git a/xls/modules/zstd/priority_encoder.v b/xls/modules/zstd/external/priority_encoder.v similarity index 100% rename from xls/modules/zstd/priority_encoder.v rename to xls/modules/zstd/external/priority_encoder.v diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index b696272811..cbf488faab 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -291,6 +291,8 @@ async def test_decoder(dut, seed, block_type, scoreboard, axi_buses, xls_channel expected_decoded_frame = DecompressFrame(encoded.read()) encoded.close() + reference_memory = SparseMemory(mem_size) + reference_memory.write(obuf_addr, expected_decoded_frame) expected_output_packets = generate_expected_output(expected_decoded_frame) assert_expected_output = Event() @@ -303,12 +305,16 @@ async def test_decoder(dut, seed, block_type, scoreboard, axi_buses, xls_channel await configure_decoder(cpu, ibuf_addr, obuf_addr) await start_decoder(cpu) - await assert_expected_output.wait() + await assert_notify.wait() await wait_for_idle(cpu) - # TODO: Check decoded frame in memory under `obuf_addr` when ZstdDecoder - # will fully support memory output interface + # Read decoded frame in chunks of AXI_DATA_W length + # Compare against frame decompressed with the reference library + for read_op in range(0, ((len(expected_decoded_frame) + (AXI_DATA_W_BYTES - 1)) // AXI_DATA_W_BYTES)): + addr = obuf_addr + (read_op * AXI_DATA_W_BYTES) + mem_contents = memory.read(addr, AXI_DATA_W_BYTES) + exp_mem_contents = reference_memory.read(addr, AXI_DATA_W_BYTES) + assert mem_contents == exp_mem_contents, "{} bytes of memory contents at address {} don't match the expected contents:\n{}\nvs\n{}".format(AXI_DATA_W_BYTES, hex(addr), hex(int.from_bytes(mem_contents, byteorder='little')), hex(int.from_bytes(exp_mem_contents, byteorder='little'))) - await assert_notify.wait() await ClockCycles(dut.clk, 20) @cocotb.test(timeout_time=50, timeout_unit="ms") @@ -320,73 +326,73 @@ async def zstd_reset_test(dut): await test_reset(dut) #FIXME: Rework testbench to decode multiple ZSTD frames in one test -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_1(dut): block_type = BlockType.RAW (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 1, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_2(dut): block_type = BlockType.RAW (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 2, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_3(dut): block_type = BlockType.RAW (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 3, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_4(dut): block_type = BlockType.RAW (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 4, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_5(dut): block_type = BlockType.RAW (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 5, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_1(dut): block_type = BlockType.RLE (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 1, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_2(dut): block_type = BlockType.RLE (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 2, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_3(dut): block_type = BlockType.RLE (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 3, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_4(dut): block_type = BlockType.RLE (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 4, block_type, scoreboard, axi_buses, xls_channels, cpu) -@cocotb.test(timeout_time=20000, timeout_unit="ms") +@cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_5(dut): block_type = BlockType.RLE (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) await test_decoder(dut, 5, block_type, scoreboard, axi_buses, xls_channels, cpu) -#@cocotb.test(timeout_time=20000, timeout_unit="ms") +#@cocotb.test(timeout_time=1000, timeout_unit="ms") #async def zstd_compressed_frames_test(dut): # test_cases = 1 # block_type = BlockType.COMPRESSED # await test_decoder(dut, test_cases, block_type) # -#@cocotb.test(timeout_time=20000, timeout_unit="ms") +#@cocotb.test(timeout_time=1000, timeout_unit="ms") #async def zstd_random_frames_test(dut): # test_cases = 1 # block_type = BlockType.RANDOM @@ -398,10 +404,15 @@ async def zstd_rle_frames_test_5(dut): "xls/modules/zstd/zstd_dec.v", "xls/modules/zstd/rtl/xls_fifo_wrapper.sv", "xls/modules/zstd/rtl/zstd_dec_wrapper.sv", - "xls/modules/zstd/axi_interconnect_wrapper.v", - "xls/modules/zstd/axi_interconnect.v", - "xls/modules/zstd/arbiter.v", - "xls/modules/zstd/priority_encoder.v", + "xls/modules/zstd/external/axi_crossbar_wrapper.v", + "xls/modules/zstd/external/axi_crossbar.v", + "xls/modules/zstd/external/axi_crossbar_rd.v", + "xls/modules/zstd/external/axi_crossbar_wr.v", + "xls/modules/zstd/external/axi_crossbar_addr.v", + "xls/modules/zstd/external/axi_register_rd.v", + "xls/modules/zstd/external/axi_register_wr.v", + "xls/modules/zstd/external/arbiter.v", + "xls/modules/zstd/external/priority_encoder.v", ] test_module=[Path(__file__).stem] run_test(toplevel, test_module, verilog_sources) From 9cf5c38bd0040009bd75dfd17479335a589a3fe9 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Mon, 12 May 2025 19:58:23 +0200 Subject: [PATCH 10/30] modules/zstd/zstd_dec: Remove stream-based output interface Adjust cocotb test to: * Removal of Repacketizer proc * Removal of stream-based output channels from * SequenceExecutor * ZstdDecoder Internal-tag: [#67272] Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/zstd_dec_cocotb_test.py | 79 +++++++----------------- 1 file changed, 22 insertions(+), 57 deletions(-) diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index cbf488faab..64e8cf586a 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -44,7 +44,6 @@ AXI_DATA_W_BYTES = AXI_DATA_W // 8 MAX_ENCODED_FRAME_SIZE_B = 16384 NOTIFY_CHANNEL = "notify" -OUTPUT_CHANNEL = "output" RESET_CHANNEL = "reset" # Override default widths of AXI response signals @@ -69,12 +68,6 @@ class NotifyStruct(XLSStruct): class ResetStruct(XLSStruct): pass -@xls_dataclass -class OutputStruct(XLSStruct): - data: 64 - length: 32 - last: 1 - class CSR(Enum): """ Maps the offsets to the ZSTD Decoder registers @@ -215,23 +208,6 @@ async def wait_for_idle(cpu, timeout=100): timeout -= 1 assert (timeout != 0) -def generate_expected_output(decoded_frame): - packets = [] - frame_len = len(decoded_frame) - last_len = frame_len % 8 - for i in range(frame_len // 8): - start_id = i * 8 - end_id = start_id + 8 - packet_data = int.from_bytes(decoded_frame[start_id:end_id], byteorder='little') - last_packet = (end_id==frame_len) - packet = OutputStruct(data=packet_data, length=64, last=last_packet) - packets.append(packet) - if (last_len): - packet_data = int.from_bytes(decoded_frame[-last_len:], byteorder='little') - packet = OutputStruct(data=packet_data, length=last_len*8, last=True) - packets.append(packet) - return packets - async def reset_dut(dut, rst_len=10): dut.rst.setimmediatevalue(0) await ClockCycles(dut.clk, rst_len) @@ -249,8 +225,6 @@ def prepare_test_environment(dut): clock = Clock(dut.clk, 10, units="us") cocotb.start_soon(clock.start()) - scoreboard = Scoreboard(dut) - memory_bus = connect_axi_bus(dut, "memory") csr_bus = connect_axi_bus(dut, "csr") axi_buses = { @@ -259,21 +233,18 @@ def prepare_test_environment(dut): } notify = connect_xls_channel(dut, NOTIFY_CHANNEL, NotifyStruct) - output = connect_xls_channel(dut, OUTPUT_CHANNEL, OutputStruct) xls_channels = { "notify": notify, - "output": output } cpu = AxiMaster(csr_bus, dut.clk, dut.rst) - return (scoreboard, axi_buses, xls_channels, cpu) + return (axi_buses, xls_channels, cpu) -async def test_decoder(dut, seed, block_type, scoreboard, axi_buses, xls_channels, cpu): +async def test_decoder(dut, seed, block_type, axi_buses, xls_channels, cpu): memory_bus = axi_buses["memory"] csr_bus = axi_buses["csr"] (notify_channel, notify_monitor) = xls_channels[NOTIFY_CHANNEL] - (output_channel, output_monitor) = xls_channels[OUTPUT_CHANNEL] assert_notify = Event() set_termination_event(notify_monitor, assert_notify, 1) @@ -293,12 +264,6 @@ async def test_decoder(dut, seed, block_type, scoreboard, axi_buses, xls_channel encoded.close() reference_memory = SparseMemory(mem_size) reference_memory.write(obuf_addr, expected_decoded_frame) - expected_output_packets = generate_expected_output(expected_decoded_frame) - - assert_expected_output = Event() - set_termination_event(output_monitor, assert_expected_output, len(expected_output_packets)) - # Monitor stream output for packets with the decoded ZSTD frame - scoreboard.add_interface(output_monitor, expected_output_packets) # Initialise testbench memory with generated ZSTD frame memory = AxiRamFromFile(bus=memory_bus, clock=dut.clk, reset=dut.rst, path=encoded.name, size=mem_size) @@ -329,62 +294,62 @@ async def zstd_reset_test(dut): @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_1(dut): block_type = BlockType.RAW - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 1, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 1, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_2(dut): block_type = BlockType.RAW - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 2, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 2, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_3(dut): block_type = BlockType.RAW - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 3, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 3, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_4(dut): block_type = BlockType.RAW - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 4, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 4, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_raw_frames_test_5(dut): block_type = BlockType.RAW - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 5, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 5, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_1(dut): block_type = BlockType.RLE - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 1, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 1, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_2(dut): block_type = BlockType.RLE - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 2, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 2, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_3(dut): block_type = BlockType.RLE - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 3, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 3, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_4(dut): block_type = BlockType.RLE - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 4, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 4, block_type, axi_buses, xls_channels, cpu) @cocotb.test(timeout_time=1000, timeout_unit="ms") async def zstd_rle_frames_test_5(dut): block_type = BlockType.RLE - (scoreboard, axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 5, block_type, scoreboard, axi_buses, xls_channels, cpu) + (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) + await test_decoder(dut, 5, block_type, axi_buses, xls_channels, cpu) #@cocotb.test(timeout_time=1000, timeout_unit="ms") #async def zstd_compressed_frames_test(dut): From e257130be7f065249f3ee44acdee8fb6fdea36d6 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Mon, 18 Nov 2024 10:31:11 +0100 Subject: [PATCH 11/30] modules/zstd/zstd_dec_cocotb_test: Improve Verilog simulation * Decode multiple ZSTD frames in a single cocotb testbench * Add one cocotb testbench per type of the ZSTD frames: * Frames with RAW blocks only * Frames with RLE blocks only * Frames with Compressed blocks only (disabled) * Frames with mixed blocks (disabled) Internal-tag: [#67272] Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/zstd_dec_cocotb_test.py | 88 ++++++------------------ 1 file changed, 20 insertions(+), 68 deletions(-) diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index 64e8cf586a..3a4bfbf70f 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -232,20 +232,15 @@ def prepare_test_environment(dut): "csr": csr_bus } - notify = connect_xls_channel(dut, NOTIFY_CHANNEL, NotifyStruct) - xls_channels = { - "notify": notify, - } - cpu = AxiMaster(csr_bus, dut.clk, dut.rst) - return (axi_buses, xls_channels, cpu) + return (axi_buses, cpu) -async def test_decoder(dut, seed, block_type, axi_buses, xls_channels, cpu): +async def test_decoder(dut, seed, block_type, axi_buses, cpu): memory_bus = axi_buses["memory"] csr_bus = axi_buses["csr"] - (notify_channel, notify_monitor) = xls_channels[NOTIFY_CHANNEL] + (notify_channel, notify_monitor) = connect_xls_channel(dut, NOTIFY_CHANNEL, NotifyStruct) assert_notify = Event() set_termination_event(notify_monitor, assert_notify, 1) @@ -282,6 +277,12 @@ async def test_decoder(dut, seed, block_type, axi_buses, xls_channels, cpu): await ClockCycles(dut.clk, 20) +async def testing_routine(dut, test_cases=1, block_type=BlockType.RANDOM): + (axi_buses, cpu) = prepare_test_environment(dut) + for test_case in range(test_cases): + await test_decoder(dut, test_case, block_type, axi_buses, cpu) + print("Decoding {} ZSTD frames done".format(block_type.name)) + @cocotb.test(timeout_time=50, timeout_unit="ms") async def zstd_csr_test(dut): await test_csr(dut) @@ -290,78 +291,29 @@ async def zstd_csr_test(dut): async def zstd_reset_test(dut): await test_reset(dut) -#FIXME: Rework testbench to decode multiple ZSTD frames in one test -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_raw_frames_test_1(dut): - block_type = BlockType.RAW - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 1, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_raw_frames_test_2(dut): - block_type = BlockType.RAW - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 2, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_raw_frames_test_3(dut): - block_type = BlockType.RAW - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 3, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_raw_frames_test_4(dut): - block_type = BlockType.RAW - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 4, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_raw_frames_test_5(dut): +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def zstd_raw_frames_test(dut): + test_cases = 5 block_type = BlockType.RAW - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 5, block_type, axi_buses, xls_channels, cpu) + await testing_routine(dut, test_cases, block_type) -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_rle_frames_test_1(dut): +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def zstd_rle_frames_test(dut): + test_cases = 5 block_type = BlockType.RLE - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 1, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_rle_frames_test_2(dut): - block_type = BlockType.RLE - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 2, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_rle_frames_test_3(dut): - block_type = BlockType.RLE - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 3, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_rle_frames_test_4(dut): - block_type = BlockType.RLE - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 4, block_type, axi_buses, xls_channels, cpu) - -@cocotb.test(timeout_time=1000, timeout_unit="ms") -async def zstd_rle_frames_test_5(dut): - block_type = BlockType.RLE - (axi_buses, xls_channels, cpu) = prepare_test_environment(dut) - await test_decoder(dut, 5, block_type, axi_buses, xls_channels, cpu) + await testing_routine(dut, test_cases, block_type) #@cocotb.test(timeout_time=1000, timeout_unit="ms") #async def zstd_compressed_frames_test(dut): # test_cases = 1 # block_type = BlockType.COMPRESSED -# await test_decoder(dut, test_cases, block_type) -# +# await testing_routine(dut, test_cases, block_type) + #@cocotb.test(timeout_time=1000, timeout_unit="ms") #async def zstd_random_frames_test(dut): # test_cases = 1 # block_type = BlockType.RANDOM -# await test_decoder(dut, test_cases, block_type) +# await testing_routine(dut, test_cases, block_type) if __name__ == "__main__": toplevel = "zstd_dec_wrapper" From 93c265d8470dbdc99af29266ebe10038ed384a21 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Thu, 2 Jan 2025 11:21:32 +0100 Subject: [PATCH 12/30] modules/zstd/memory/mem_writer: Reduce the amount of random test cases Caused by timeouts after rebase - looks like regression in the performance of codegen Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/memory/mem_writer_cocotb_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xls/modules/zstd/memory/mem_writer_cocotb_test.py b/xls/modules/zstd/memory/mem_writer_cocotb_test.py index b617c41fa2..1569227065 100644 --- a/xls/modules/zstd/memory/mem_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_writer_cocotb_test.py @@ -206,7 +206,7 @@ async def ram_test_not_full_packets(dut): @cocotb.test(timeout_time=5000, timeout_unit="ms") async def ram_test_random(dut): mem_size = 2**ADDR_WIDTH - test_count = 200 + test_count = 50 (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_random(test_count, mem_size) await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) From 0c8a6595c506cdb7c9a3f843bcce3886bbf776a5 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Mon, 7 Apr 2025 17:24:48 +0200 Subject: [PATCH 13/30] modules/zstd/memory: Move verilog sources to rtl subdirectory Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/BUILD | 1 + xls/modules/zstd/memory/BUILD | 8 ++-- .../zstd/memory/axi_writer_cocotb_test.py | 2 +- .../zstd/memory/mem_reader_cocotb_test.py | 3 +- .../zstd/memory/mem_writer_cocotb_test.py | 3 +- xls/modules/zstd/memory/rtl/BUILD | 39 +++++++++++++++++++ .../memory/{ => rtl}/axi_writer_wrapper.v | 3 ++ .../memory/{ => rtl}/mem_reader_wrapper.v | 3 ++ .../memory/{ => rtl}/mem_writer_wrapper.v | 3 ++ 9 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 xls/modules/zstd/memory/rtl/BUILD rename xls/modules/zstd/memory/{ => rtl}/axi_writer_wrapper.v (96%) rename xls/modules/zstd/memory/{ => rtl}/mem_reader_wrapper.v (96%) rename xls/modules/zstd/memory/{ => rtl}/mem_writer_wrapper.v (98%) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 91a48dd761..fa75755341 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -1722,6 +1722,7 @@ py_test( "//xls/modules/zstd/external:axi_register_rd.v", "//xls/modules/zstd/external:axi_register_wr.v", "//xls/modules/zstd/external:priority_encoder.v", + "//xls/modules/zstd/rtl:xls_fifo_wrapper.sv", "//xls/modules/zstd/rtl:zstd_dec_wrapper.sv", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", diff --git a/xls/modules/zstd/memory/BUILD b/xls/modules/zstd/memory/BUILD index 84f9933b1d..461b3518e4 100644 --- a/xls/modules/zstd/memory/BUILD +++ b/xls/modules/zstd/memory/BUILD @@ -553,8 +553,7 @@ py_test( srcs = ["mem_reader_cocotb_test.py"], data = [ ":mem_reader_adv.v", - ":mem_reader_wrapper.v", - "//xls/modules/zstd:xls_fifo_wrapper.sv", + "//xls/modules/zstd/memory/rtl:mem_reader_wrapper.v", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], @@ -650,7 +649,7 @@ py_test( srcs = ["axi_writer_cocotb_test.py"], data = [ ":axi_writer.v", - ":axi_writer_wrapper.v", + "//xls/modules/zstd/memory/rtl:axi_writer_wrapper.v", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], @@ -816,8 +815,7 @@ py_test( srcs = ["mem_writer_cocotb_test.py"], data = [ ":mem_writer.v", - ":mem_writer_wrapper.v", - "//xls/modules/zstd:xls_fifo_wrapper.sv", + "//xls/modules/zstd/memory/rtl:mem_writer_wrapper.v", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], diff --git a/xls/modules/zstd/memory/axi_writer_cocotb_test.py b/xls/modules/zstd/memory/axi_writer_cocotb_test.py index b30876a687..d655c6f8e0 100644 --- a/xls/modules/zstd/memory/axi_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/axi_writer_cocotb_test.py @@ -239,7 +239,7 @@ def generate_test_data_arbitrary(mem_size): toplevel = "axi_writer_wrapper" verilog_sources = [ "xls/modules/zstd/memory/axi_writer.v", - "xls/modules/zstd/memory/axi_writer_wrapper.v", + "xls/modules/zstd/memory/rtl/axi_writer_wrapper.v", ] test_module=[Path(__file__).stem] run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/mem_reader_cocotb_test.py b/xls/modules/zstd/memory/mem_reader_cocotb_test.py index 36c90cea1d..3e48904f6a 100644 --- a/xls/modules/zstd/memory/mem_reader_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_reader_cocotb_test.py @@ -264,9 +264,8 @@ async def mem_reader_aligned_transfer_shorter_than_bus4(dut): toplevel = "mem_reader_wrapper" verilog_sources = [ - "xls/modules/zstd/xls_fifo_wrapper.sv", "xls/modules/zstd/memory/mem_reader_adv.v", - "xls/modules/zstd/memory/mem_reader_wrapper.v", + "xls/modules/zstd/memory/rtl/mem_reader_wrapper.v", ] test_module = [Path(__file__).stem] run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/mem_writer_cocotb_test.py b/xls/modules/zstd/memory/mem_writer_cocotb_test.py index 1569227065..69b39a7894 100644 --- a/xls/modules/zstd/memory/mem_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_writer_cocotb_test.py @@ -442,9 +442,8 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): if __name__ == "__main__": toplevel = "mem_writer_wrapper" verilog_sources = [ - "xls/modules/zstd/xls_fifo_wrapper.sv", "xls/modules/zstd/memory/mem_writer.v", - "xls/modules/zstd/memory/mem_writer_wrapper.v", + "xls/modules/zstd/memory/rtl/mem_writer_wrapper.v", ] test_module=[Path(__file__).stem] run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/rtl/BUILD b/xls/modules/zstd/memory/rtl/BUILD new file mode 100644 index 0000000000..96029da06d --- /dev/null +++ b/xls/modules/zstd/memory/rtl/BUILD @@ -0,0 +1,39 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Collection of simulation sources + +This package exports verilog sources required by the Memory Writer and Read +in the verilog tests. + +The sources contain: + * Wrapper for the MemReader used in the verilog tests + * Wrapper for the MemWriter used in the verilog tests + * Wrapper for the AxiWriter used in the verilog tests + +""" + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//xls:xls_users"], + licenses = ["notice"], +) + +exports_files( + [ + "mem_reader_wrapper.v", + "mem_writer_wrapper.v", + "axi_writer_wrapper.v", + ], +) diff --git a/xls/modules/zstd/memory/axi_writer_wrapper.v b/xls/modules/zstd/memory/rtl/axi_writer_wrapper.v similarity index 96% rename from xls/modules/zstd/memory/axi_writer_wrapper.v rename to xls/modules/zstd/memory/rtl/axi_writer_wrapper.v index 556f839284..15788cd41d 100644 --- a/xls/modules/zstd/memory/axi_writer_wrapper.v +++ b/xls/modules/zstd/memory/rtl/axi_writer_wrapper.v @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +// This module wraps the AXI Writer verilog sources generated from DSLX to +// form a DUT for verilog tests with consistent IO. + `default_nettype none module axi_writer_wrapper ( diff --git a/xls/modules/zstd/memory/mem_reader_wrapper.v b/xls/modules/zstd/memory/rtl/mem_reader_wrapper.v similarity index 96% rename from xls/modules/zstd/memory/mem_reader_wrapper.v rename to xls/modules/zstd/memory/rtl/mem_reader_wrapper.v index 3601bcbb0e..0dfd2dd941 100644 --- a/xls/modules/zstd/memory/mem_reader_wrapper.v +++ b/xls/modules/zstd/memory/rtl/mem_reader_wrapper.v @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +// This module wraps the Memory Reader verilog sources generated from DSLX to +// form a DUT for verilog tests with consistent IO. + `default_nettype none module mem_reader_wrapper #( diff --git a/xls/modules/zstd/memory/mem_writer_wrapper.v b/xls/modules/zstd/memory/rtl/mem_writer_wrapper.v similarity index 98% rename from xls/modules/zstd/memory/mem_writer_wrapper.v rename to xls/modules/zstd/memory/rtl/mem_writer_wrapper.v index c7513af58a..958383c282 100644 --- a/xls/modules/zstd/memory/mem_writer_wrapper.v +++ b/xls/modules/zstd/memory/rtl/mem_writer_wrapper.v @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +// This module wraps the Memory Writer verilog sources generated from DSLX to +// form a DUT for verilog tests with consistent IO. + `default_nettype none module mem_writer_wrapper ( From 6e8fd9ae3228fa054cd25e8e9a0be399f5bc315c Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Mon, 7 Apr 2025 15:44:54 +0200 Subject: [PATCH 14/30] xls/modules/zstd/external: Add docstring and license for third party sources Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/external/BUILD | 15 +++++++++++++++ xls/modules/zstd/external/LICENSE | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 xls/modules/zstd/external/LICENSE diff --git a/xls/modules/zstd/external/BUILD b/xls/modules/zstd/external/BUILD index f24cb69fe0..f0e3c97626 100644 --- a/xls/modules/zstd/external/BUILD +++ b/xls/modules/zstd/external/BUILD @@ -12,6 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Collection of external RTL sources + +This package exports external verilog sources required by the ZSTD Decoder +in the verilog tests. + +The exported files come from the Open Source library of the AXI4 and AXI4 lite +bus components released under MIT license. + +The sources contain an implementation of the AXI4 crossbar which is used in the +verilog tests of the ZSTD Decoder to connect multiple AXI interfaces into a single +AXI interface that forms the IO of the ZSTD Decoder verilog wrapper used in the tests. + +Source: https://github.com/alexforencich/verilog-axi +""" + package( default_applicable_licenses = ["//:license"], default_visibility = ["//xls:xls_users"], diff --git a/xls/modules/zstd/external/LICENSE b/xls/modules/zstd/external/LICENSE new file mode 100644 index 0000000000..6923387c75 --- /dev/null +++ b/xls/modules/zstd/external/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018 Alex Forencich + +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. From 8d73bd93820ab18277d50f85a0fc4e2d25d917b3 Mon Sep 17 00:00:00 2001 From: Pawel Czarnecki Date: Tue, 13 May 2025 19:14:28 +0200 Subject: [PATCH 15/30] modules/zstd: Adjust cocotb test to removal of RESET CSR Signed-off-by: Pawel Czarnecki --- xls/modules/zstd/zstd_dec_cocotb_test.py | 25 ++++-------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index 3a4bfbf70f..a5ca1daec6 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -64,19 +64,14 @@ class NotifyStruct(XLSStruct): pass -@xls_dataclass -class ResetStruct(XLSStruct): - pass - class CSR(Enum): """ Maps the offsets to the ZSTD Decoder registers """ Status = 0 Start = 1 - Reset = 2 - InputBuffer = 3 - OutputBuffer = 4 + InputBuffer = 2 + OutputBuffer = 3 class Status(Enum): """ @@ -146,9 +141,6 @@ async def test_csr(dut): await ClockCycles(dut.clk, 10) i = 0 for reg in CSR: - # Reset CSR tested in a separate test case - if (reg == CSR.Reset): - continue expected_src = bytearray.fromhex("0DF0AD8BEFBEADDE") assert len(expected_src) >= AXI_DATA_W_BYTES expected = expected_src[-AXI_DATA_W_BYTES:] @@ -165,18 +157,9 @@ async def test_reset(dut): await reset_dut(dut, 50) - (reset_channel, reset_monitor) = connect_xls_channel(dut, RESET_CHANNEL, ResetStruct) - csr_bus = connect_axi_bus(dut, "csr") cpu = AxiMaster(csr_bus, dut.clk, dut.rst) - scoreboard = Scoreboard(dut) - - rst_struct = ResetStruct() - # Expect single reset signal on reset output channel - expected_reset = [rst_struct] - scoreboard.add_interface(reset_monitor, expected_reset) - await ClockCycles(dut.clk, 10) await start_decoder(cpu) timeout = 10 @@ -186,7 +169,7 @@ async def test_reset(dut): timeout -= 1 assert (timeout != 0) - await csr_write(cpu, CSR.Reset, 0x1) + await reset_dut(dut, 50) await wait_for_idle(cpu, 10) await ClockCycles(dut.clk, 10) @@ -194,7 +177,7 @@ async def test_reset(dut): async def configure_decoder(cpu, ibuf_addr, obuf_addr): status = await csr_read(cpu, CSR.Status) if int.from_bytes(status.data, byteorder='little') != Status.IDLE.value: - await csr_write(cpu, CSR.Reset, 0x1) + await reset_dut(dut, 50) await csr_write(cpu, CSR.InputBuffer, ibuf_addr) await csr_write(cpu, CSR.OutputBuffer, obuf_addr) From 4ec4493111012027269fc46f842b7aca764009dc Mon Sep 17 00:00:00 2001 From: Wojciech Sipak Date: Mon, 7 Apr 2025 15:45:34 +0200 Subject: [PATCH 16/30] Style changes Improve formatting, wording and fix lint issues Co-authored-by: Dominik Lau Co-authored-by: Pawel Czarnecki Signed-off-by: Wojciech Sipak --- xls/modules/zstd/cocotb/channel.py | 39 +- xls/modules/zstd/cocotb/data_generator.py | 17 +- xls/modules/zstd/cocotb/memory.py | 16 +- xls/modules/zstd/cocotb/scoreboard.py | 25 +- xls/modules/zstd/cocotb/utils.py | 20 +- xls/modules/zstd/cocotb/xlsstruct.py | 105 ++-- .../zstd/memory/axi_writer_cocotb_test.py | 228 +++++--- .../zstd/memory/mem_reader_cocotb_test.py | 103 ++-- .../zstd/memory/mem_writer_cocotb_test.py | 517 ++++++++++++++---- .../zstd/memory/rtl/mem_reader_wrapper.v | 24 +- .../zstd/memory/rtl/mem_writer_wrapper.v | 62 ++- xls/modules/zstd/zstd_dec_cocotb_test.py | 204 +++---- xls/modules/zstd/zstd_frame_dslx.py | 95 ++-- 13 files changed, 951 insertions(+), 504 deletions(-) diff --git a/xls/modules/zstd/cocotb/channel.py b/xls/modules/zstd/cocotb/channel.py index 0970ab6e9b..6b6e546e86 100644 --- a/xls/modules/zstd/cocotb/channel.py +++ b/xls/modules/zstd/cocotb/channel.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Cocotb interfaces for XLS channels using data, valid, and ready signals.""" + from typing import Any, Sequence, Type, Union import cocotb @@ -30,18 +32,21 @@ class XLSChannel(Bus): + """Represents an XLS- channel with ready/valid handshake.""" _signals = XLS_CHANNEL_SIGNALS _optional_signals = XLS_CHANNEL_OPTIONAL_SIGNALS def __init__(self, entity, name, clk, *, start_now=False, **kwargs: Any): - super().__init__(entity, name, self._signals, self._optional_signals, **kwargs) + super().__init__( + entity, name, self._signals, self._optional_signals, **kwargs + ) self.clk = clk if start_now: self.start_recv_loop() @cocotb.coroutine async def recv_channel(self): - """Cocotb coroutine that acts as a proc receiving data from a channel""" + """Cocotb coroutine that acts as a proc receiving data from a channel.""" self.rdy.setimmediatevalue(1) while True: await RisingEdge(self.clk) @@ -51,20 +56,34 @@ def start_recv_loop(self): class XLSChannelDriver(BusDriver): + """Drives transactions on an XLS channel.""" _signals = XLS_CHANNEL_SIGNALS _optional_signals = XLS_CHANNEL_OPTIONAL_SIGNALS - def __init__(self, entity: SimHandleBase, name: str, clock: SimHandleBase, **kwargs: Any): + def __init__( + self, + entity: SimHandleBase, + name: str, + clock: SimHandleBase, + **kwargs: Any + ): BusDriver.__init__(self, entity, name, clock, **kwargs) self.bus.data.setimmediatevalue(0) self.bus.vld.setimmediatevalue(0) - async def _driver_send(self, transaction: Transaction, sync: bool = True, **kwargs: Any) -> None: + async def _driver_send( + self, + transaction: Transaction, + sync: bool = True, + **kwargs: Any + ) -> None: if sync: await RisingEdge(self.clock) - data_to_send = (transaction if isinstance(transaction, Sequence) else [transaction]) + data_to_send = ( + transaction if isinstance(transaction, Sequence) else [transaction] + ) for word in data_to_send: self.bus.vld.value = 1 @@ -79,10 +98,18 @@ async def _driver_send(self, transaction: Transaction, sync: bool = True, **kwar class XLSChannelMonitor(BusMonitor): + """Monitors and decodes transactions on an XLS channel.""" _signals = XLS_CHANNEL_SIGNALS _optional_signals = XLS_CHANNEL_OPTIONAL_SIGNALS - def __init__(self, entity: SimHandleBase, name: str, clock: SimHandleBase, struct: Type[XLSStruct], **kwargs: Any): + def __init__( + self, + entity: SimHandleBase, + name: str, + clock: SimHandleBase, + struct: Type[XLSStruct], + **kwargs: Any + ): BusMonitor.__init__(self, entity, name, clock, **kwargs) self.struct = struct diff --git a/xls/modules/zstd/cocotb/data_generator.py b/xls/modules/zstd/cocotb/data_generator.py index 72b60c5eee..46a74acbfc 100644 --- a/xls/modules/zstd/cocotb/data_generator.py +++ b/xls/modules/zstd/cocotb/data_generator.py @@ -12,14 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -from pathlib import Path -from enum import Enum +"""Module for generating and decompressing test frames.""" + +import pathlib +import enum from xls.common import runfiles import subprocess import zstandard -class BlockType(Enum): +class BlockType(enum.Enum): + """Enum encoding of ZSTD block types.""" + RAW = 0 RLE = 1 COMPRESSED = 2 @@ -33,10 +37,12 @@ def from_string(s): try: return BlockType[s] except KeyError as e: - raise ValueError(str(e)) + raise ValueError(str(e)) from e def CallDecodecorpus(args): - decodecorpus = Path(runfiles.get_path("decodecorpus", repository = "zstd")) + decodecorpus = pathlib.Path( + runfiles.get_path("decodecorpus", repository = "zstd") + ) cmd = args cmd.insert(0, str(decodecorpus)) cmd_concat = " ".join(cmd) @@ -58,4 +64,3 @@ def GenerateFrame(seed, btype, output_path): args.append("-vvvvvvv") CallDecodecorpus(args) - diff --git a/xls/modules/zstd/cocotb/memory.py b/xls/modules/zstd/cocotb/memory.py index 52e512e053..a07ef33923 100644 --- a/xls/modules/zstd/cocotb/memory.py +++ b/xls/modules/zstd/cocotb/memory.py @@ -12,13 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. +""" +Extensions of the cocotb AXI RAM models to memory contents from a binary file. +""" + import os -from cocotbext.axi.axi_ram import AxiRam, AxiRamRead, AxiRamWrite +from cocotbext.axi.axi_ram import AxiRam +from cocotbext.axi.axi_ram import AxiRamRead +from cocotbext.axi.axi_ram import AxiRamWrite from cocotbext.axi.sparse_memory import SparseMemory -def init_axi_mem(path: os.PathLike, kwargs): +def init_axi_mem(path: os.PathLike[str], kwargs): with open(path, "rb") as f: sparse_mem = SparseMemory(size=kwargs["size"]) sparse_mem.write(0x0, f.read()) @@ -26,18 +32,18 @@ def init_axi_mem(path: os.PathLike, kwargs): class AxiRamReadFromFile(AxiRamRead): - def __init__(self, *args, path: os.PathLike, **kwargs): + def __init__(self, *args, path: os.PathLike[str], **kwargs): init_axi_mem(path, kwargs) super().__init__(*args, **kwargs) class AxiRamFromFile(AxiRam): - def __init__(self, *args, path: os.PathLike, **kwargs): + def __init__(self, *args, path: os.PathLike[str], **kwargs): init_axi_mem(path, kwargs) super().__init__(*args, **kwargs) class AxiRamWriteFromFile(AxiRamWrite): - def __init__(self, *args, path: os.PathLike, **kwargs): + def __init__(self, *args, path: os.PathLike[str], **kwargs): init_axi_mem(path, kwargs) super().__init__(*args, **kwargs) diff --git a/xls/modules/zstd/cocotb/scoreboard.py b/xls/modules/zstd/cocotb/scoreboard.py index b9b64ca6e2..b3dfca1e3a 100644 --- a/xls/modules/zstd/cocotb/scoreboard.py +++ b/xls/modules/zstd/cocotb/scoreboard.py @@ -12,8 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -from dataclasses import dataclass -from queue import Queue +"""Scoreboard creator for measuring request-response latency. + +Tracks transactions from channel monitors, computes cycle-based latency, +and logs results. +""" + +import dataclasses +import queue from cocotb.clock import Clock from cocotb.log import SimLog @@ -23,20 +29,26 @@ from xls.modules.zstd.cocotb.xlsstruct import XLSStruct -@dataclass +@dataclasses.dataclass class LatencyQueueItem: + """ + Data container for items in a latency queue. + """ + transaction: XLSStruct timestamp: int class LatencyScoreboard: + """Tracks and reports latency between request and response transactions.""" + def __init__(self, dut, clock: Clock, req_monitor: XLSChannelMonitor, resp_monitor: XLSChannelMonitor): self.dut = dut self.log = SimLog(f"zstd.cocotb.scoreboard.{self.dut._name}") self.clock = clock self.req_monitor = req_monitor self.resp_monitor = resp_monitor - self.pending_req = Queue() + self.pending_req = queue.Queue() self.results = [] self.req_monitor.add_callback(self._req_callback) @@ -48,7 +60,7 @@ def _current_cycle(self): def _req_callback(self, transaction: XLSStruct): self.pending_req.put(LatencyQueueItem(transaction, self._current_cycle())) - def _resp_callback(self, transaction: XLSStruct): + def _resp_callback(self, unused_transaction: XLSStruct): latency_item = self.pending_req.get() self.results.append(self._current_cycle() - latency_item.timestamp) @@ -56,11 +68,12 @@ def average_latency(self): return sum(self.results)/len(self.results) def report_result(self): + """Logs a summary of latency measurements and any unfulfilled requests.""" if not self.pending_req.empty(): self.log.warning(f"There are unfulfilled requests from channel {self.req_monitor.name}") while not self.pending_req.empty(): self.log.warning(f"Unfulfilled request: {self.pending_req.get()}") - if len(self.results) > 0: + if self.results: self.log.info(f"Latency report - 1st latency: {self.results[0]}") if len(self.results) > 1: self.log.info(f"Latency report - 2nd latency: {self.results[1]}") diff --git a/xls/modules/zstd/cocotb/utils.py b/xls/modules/zstd/cocotb/utils.py index 0930a92932..7fda01b0b9 100644 --- a/xls/modules/zstd/cocotb/utils.py +++ b/xls/modules/zstd/cocotb/utils.py @@ -12,25 +12,33 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Helpers for setting up and running simulations using Icarus Verilog with Cocotb.""" + import os -from pathlib import Path +import pathlib import cocotb -from cocotb.runner import check_results_file, get_runner +from cocotb.runner import check_results_file +from cocotb.runner import get_runner from cocotb.triggers import ClockCycles from xls.common import runfiles def setup_com_iverilog(): - iverilog_path = Path(runfiles.get_path("iverilog", repository = "com_icarus_iverilog")) - vvp_path = Path(runfiles.get_path("vvp", repository = "com_icarus_iverilog")) + iverilog_path = pathlib.Path( + runfiles.get_path("iverilog", repository = "com_icarus_iverilog") + ) + vvp_path = pathlib.Path( + runfiles.get_path("vvp", repository = "com_icarus_iverilog") + ) os.environ["PATH"] += os.pathsep + str(iverilog_path.parent) os.environ["PATH"] += os.pathsep + str(vvp_path.parent) - build_dir = Path(os.environ['BUILD_WORKING_DIRECTORY'], "sim_build") + build_dir = pathlib.Path(os.environ['BUILD_WORKING_DIRECTORY'], "sim_build") return build_dir def run_test(toplevel, test_module, verilog_sources): + """Builds and runs a Cocotb testbench using Icarus Verilog.""" build_dir = setup_com_iverilog() runner = get_runner("icarus") runner.build( @@ -51,7 +59,7 @@ def run_test(toplevel, test_module, verilog_sources): @cocotb.coroutine async def reset(clk, rst, cycles=1): - """Cocotb coroutine that performs the reset""" + """Cocotb coroutine that performs the reset.""" rst.value = 1 await ClockCycles(clk, cycles) rst.value = 0 diff --git a/xls/modules/zstd/cocotb/xlsstruct.py b/xls/modules/zstd/cocotb/xlsstruct.py index a2d686a8af..131be8e663 100644 --- a/xls/modules/zstd/cocotb/xlsstruct.py +++ b/xls/modules/zstd/cocotb/xlsstruct.py @@ -12,8 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +""" +Provides utilities for defining Python representations of XLS structs. +""" + import random -from dataclasses import asdict, astuple, dataclass, fields +import dataclasses from cocotb.binary import BinaryValue @@ -22,29 +26,36 @@ class TruncationError(Exception): pass def xls_dataclass(cls): - """ - Class decorator for XLS structs. + """Class decorator for XLS structs. + Usage: - @xls_dataclass - class MyStruct(XLSStruct): - ... + @xls_dataclass + class MyStruct(XLSStruct): + ... + Args: + cls (type): The class to decorate. + + Returns: + type: The dataclass-decorated class with repr disabled. """ - return dataclass(cls, repr=False) + return dataclasses.dataclass(cls, repr=False) -@dataclass +@dataclasses.dataclass class XLSStruct: - """ - Represents XLS struct on the Python side, allowing serialization/deserialization - to/from common formats and usage with XLS{Driver, Monitor}. + """Represents XLS struct on the Python side. - The intended way to use this class is to inherit from it, specify the fields with - : [= ] syntax and decorate the inheriting class with - @XLSDataclass. Objects of this class can be instantiated and used like usual - dataclass objects, with a few extra methods and properties available. They can also - be passed as arguments to XLSChannelDriver.send and will be serialized to expected - bit vector. Class can be passed to XLSChannelMonitor ``struct`` constructor argument - to automatically deserialize all transfers to the provided struct. + Allows serialization/deserialization to/from common formats and usage with + XLS{Driver, Monitor}. + + The intended way to use this class is to inherit from it, specify the fields + with : [= ] syntax and decorate the inheriting + class with @XLSDataclass. Objects of this class can be instantiated and used + like usual dataclass objects, with a few extra methods and properties + available. They can also be passed as arguments to XLSChannelDriver.send and + will be serialized to expected bit vector. Class can be passed to + XLSChannelMonitor ``struct`` constructor argument to automatically + deserialize all transfers to the provided struct. Example: @@ -70,29 +81,26 @@ class MyStruct(XLSStruct): @classmethod def _masks(cls): - """ - Returns a list of field-sized bitmasks. + """Returns a list of field-sized bitmasks. For example for fields of widths 2, 3, 4 returns [2'b11, 3'b111, 4'b1111]. """ masks = [] - for field in fields(cls): + for field in dataclasses.fields(cls): width = field.type masks += [(1 << width) - 1] return masks @classmethod def _positions(cls): - """ - Returns a list of start positions in a bit vector for - struct's fields. + """Returns a list of start positions in a bit vector for struct's fields. For example for fields of widths 1, 2, 3, 4, 5, 6 returns [20, 18, 15, 11, 6, 0] """ positions = [] - for i, field in enumerate(fields(cls)): + for i, field in enumerate(dataclasses.fields(cls)): width = field.type if i == 0: positions += [cls.total_width - width] @@ -103,66 +111,55 @@ def _positions(cls): @classmethod @property def total_width(cls): - """ - Returns total bit width of the struct - """ - return sum(field.type for field in fields(cls)) + """Returns total bit width of the struct.""" + return sum(field.type for field in dataclasses.fields(cls)) @property def value(self): - """ - Returns struct's value as a Python integer - """ + """Returns struct's value as a Python integer.""" value = 0 masks = self._masks() positions = self._positions() - for field_val, mask, pos in zip(astuple(self), masks, positions): + for field_val, mask, pos in zip( + dataclasses.astuple(self), masks, positions): if field_val > mask: - raise TruncationError(f"Signal value is wider than its bit width") + raise TruncationError("Signal value is wider than its bit width") value |= (field_val & mask) << pos return value @property def binaryvalue(self): - """ - Returns struct's value as a cocotb.binary.BinaryValue - """ + """Returns struct's value as a cocotb.binary.BinaryValue.""" return BinaryValue(self.binstr) @property def binstr(self): - """ - Returns struct's value as a string with its binary representation - """ + """Returns struct's value as a string with its binary representation.""" return f"{self.value:>0{self.total_width}b}" @property def hexstr(self): - """ - Returns struct's value as a string with its hex representation - (without leading "0x") + """Returns struct's value as a string with its hex representation. + + The result does NOT have leading "0x". """ return f"{self.value:>0{self.total_width // 4}x}" @classmethod def from_int(cls, value): - """ - Returns an instance of the struct from Python integer - """ + """Returns an instance of the struct from Python integer.""" instance = {} masks = cls._masks() positions = cls._positions() - for field, mask, pos in zip(fields(cls), masks, positions): + for field, mask, pos in zip(dataclasses.fields(cls), masks, positions): instance[field.name] = (value >> pos) & mask return cls(**instance) @classmethod def randomize(cls): - """ - Returns an instance of the struct with all fields' values randomized - """ + """Returns an instance of the struct with all fields' values randomized.""" instance = {} - for field in fields(cls): + for field in dataclasses.fields(cls): instance[field.name] = random.randrange(0, 2**field.type) return cls(**instance) @@ -171,5 +168,7 @@ def __str__(self): def __repr__(self): classname = self.__class__.__name__ - fields = [f"{name}={hex(value)}" for name, value in asdict(self).items()] - return f"{classname}({', '.join(fields)})" + class_fields = [ + f"{name}={hex(value)}" for name, value in dataclasses.asdict(self).items() + ] + return f"{classname}({', '.join(class_fields)})" diff --git a/xls/modules/zstd/memory/axi_writer_cocotb_test.py b/xls/modules/zstd/memory/axi_writer_cocotb_test.py index d655c6f8e0..2ad396c3c6 100644 --- a/xls/modules/zstd/memory/axi_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/axi_writer_cocotb_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright 2024 The XLS Authors # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,44 +15,39 @@ import random import logging -from pathlib import Path +import pathlib import cocotb from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, Event -from cocotb.binary import BinaryValue +from cocotb.triggers import Event from cocotb_bus.scoreboard import Scoreboard -from cocotbext.axi.axis import AxiStreamSource, AxiStreamBus, AxiStreamFrame -from cocotbext.axi.axi_channels import AxiAWBus, AxiWBus, AxiBBus, AxiWriteBus, AxiAWMonitor, AxiWMonitor, AxiBMonitor, AxiBTransaction, AxiBSource, AxiBSink +from cocotbext.axi import axis +from cocotbext.axi import axi_channels from cocotbext.axi.axi_ram import AxiRamWrite from cocotbext.axi.sparse_memory import SparseMemory -from xls.modules.zstd.cocotb.channel import ( - XLSChannel, - XLSChannelDriver, - XLSChannelMonitor, -) -from xls.modules.zstd.cocotb.utils import reset, run_test -from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass +import xls.modules.zstd.cocotb.channel as xlschannel +from xls.modules.zstd.cocotb import utils +from xls.modules.zstd.cocotb import xlsstruct ID_WIDTH = 4 ADDR_WIDTH = 16 # Override default widths of AXI response signals signal_widths = {"bresp": 3} -AxiBBus._signal_widths = signal_widths -AxiBTransaction._signal_widths = signal_widths -AxiBSource._signal_widths = signal_widths -AxiBSink._signal_widths = signal_widths -AxiBMonitor._signal_widths = signal_widths - -@xls_dataclass -class AxiWriterRespStruct(XLSStruct): +axi_channels.AxiBBus._signal_widths = signal_widths +axi_channels.AxiBTransaction._signal_widths = signal_widths +axi_channels.AxiBSource._signal_widths = signal_widths +axi_channels.AxiBSink._signal_widths = signal_widths +axi_channels.AxiBMonitor._signal_widths = signal_widths + +@xlsstruct.xls_dataclass +class AxiWriterRespStruct(xlsstruct.XLSStruct): status: 1 -@xls_dataclass -class WriteRequestStruct(XLSStruct): +@xlsstruct.xls_dataclass +class WriteRequestStruct(xlsstruct.XLSStruct): address: ADDR_WIDTH length: ADDR_WIDTH @@ -65,40 +59,62 @@ def terminate_cb(_): @cocotb.test(timeout_time=20000, timeout_unit="ms") async def ram_test(dut): - GENERIC_ADDR_REQ_CHANNEL = "write_req" - GENERIC_ADDR_RESP_CHANNEL = "write_resp" - AXI_STREAM_CHANNEL = "axi_st_read" - AXI_AW_CHANNEL = "axi_aw" - AXI_W_CHANNEL = "axi_w" - AXI_B_CHANNEL = "axi_b" + generic_addr_req_channel = "write_req" + generic_addr_resp_channel = "write_resp" + axi_stream_channel = "axi_st_read" + axi_aw_channel = "axi_aw" + axi_w_channel = "axi_w" + axi_b_channel = "axi_b" terminate = Event() mem_size = 2**ADDR_WIDTH test_count = 200 - (addr_req_input, axi_st_input, addr_resp_expect, memory_verification, expected_memory) = generate_test_data_random(test_count, mem_size) + ( + addr_req_input, + axi_st_input, + addr_resp_expect, + memory_verification, + expected_memory + ) = generate_test_data_random(test_count, mem_size) dut.rst.setimmediatevalue(0) clock = Clock(dut.clk, 10, units="us") cocotb.start_soon(clock.start()) - resp_bus = XLSChannel(dut, GENERIC_ADDR_RESP_CHANNEL, dut.clk, start_now=True) - - driver_addr_req = XLSChannelDriver(dut, GENERIC_ADDR_REQ_CHANNEL, dut.clk) - driver_axi_st = AxiStreamSource(AxiStreamBus.from_prefix(dut, AXI_STREAM_CHANNEL), dut.clk, dut.rst) - - bus_axi_aw = AxiAWBus.from_prefix(dut, AXI_AW_CHANNEL) - bus_axi_w = AxiWBus.from_prefix(dut, AXI_W_CHANNEL) - bus_axi_b = AxiBBus.from_prefix(dut, AXI_B_CHANNEL) - bus_axi_write = AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) - - monitor_addr_req = XLSChannelMonitor(dut, GENERIC_ADDR_REQ_CHANNEL, dut.clk, WriteRequestStruct) - monitor_addr_resp = XLSChannelMonitor(dut, GENERIC_ADDR_RESP_CHANNEL, dut.clk, AxiWriterRespStruct) - monitor_axi_aw = AxiAWMonitor(bus_axi_aw, dut.clk, dut.rst) - monitor_axi_w = AxiWMonitor(bus_axi_w, dut.clk, dut.rst) - monitor_axi_b = AxiBMonitor(bus_axi_b, dut.clk, dut.rst) + # prefix unused objects with unused_ + # to suppress linter and keep the objects alive + unused_resp_bus = xlschannel.XLSChannel( + dut, generic_addr_resp_channel, dut.clk, start_now=True + ) + + driver_addr_req = xlschannel.XLSChannelDriver( + dut, generic_addr_req_channel, dut.clk + ) + driver_axi_st = axis.AxiStreamSource( + axis.AxiStreamBus.from_prefix(dut, axi_stream_channel), + dut.clk, + dut.rst + ) + + bus_axi_aw = axi_channels.AxiAWBus.from_prefix(dut, axi_aw_channel) + bus_axi_w = axi_channels.AxiWBus.from_prefix(dut, axi_w_channel) + bus_axi_b = axi_channels.AxiBBus.from_prefix(dut, axi_b_channel) + bus_axi_write = axi_channels.AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) + + unused_monitor_addr_req = xlschannel.XLSChannelMonitor( + dut, generic_addr_req_channel, dut.clk, WriteRequestStruct + ) + monitor_addr_resp = xlschannel.XLSChannelMonitor( + dut, generic_addr_resp_channel, dut.clk, AxiWriterRespStruct + ) + unused_monitor_axi_aw = axi_channels.AxiAWMonitor( + bus_axi_aw, dut.clk, dut.rst + ) + unused_monitor_axi_w = axi_channels.AxiWMonitor(bus_axi_w, dut.clk, dut.rst) + unused_monitor_axi_b = axi_channels.AxiBMonitor(bus_axi_b, dut.clk, dut.rst) set_termination_event(monitor_addr_resp, terminate, test_count) @@ -112,15 +128,33 @@ async def ram_test(dut): scoreboard = Scoreboard(dut) scoreboard.add_interface(monitor_addr_resp, addr_resp_expect) - await reset(dut.clk, dut.rst, cycles=10) + await utils.reset(dut.clk, dut.rst, cycles=10) await cocotb.start(driver_addr_req.send(addr_req_input)) await cocotb.start(drive_axi_st(driver_axi_st, axi_st_input)) await terminate.wait() for bundle in memory_verification: - memory_contents = bytearray(memory.read(bundle["base_address"], bundle["length"])) - expected_memory_contents = bytearray(expected_memory.read(bundle["base_address"], bundle["length"])) - assert memory_contents == expected_memory_contents, "{} bytes of memory contents at base address {}:\n{}\nvs\n{}\nHEXDUMP:\n{}\nvs\n{}".format(hex(bundle["length"]), hex(bundle["base_address"]), memory_contents, expected_memory_contents, memory.hexdump(bundle["base_address"], bundle["length"]), expected_memory.hexdump(bundle["base_address"], bundle["length"])) + memory_contents = bytearray( + memory.read(bundle["base_address"], bundle["length"]) + ) + expected_memory_contents = bytearray( + expected_memory.read(bundle["base_address"], bundle["length"]) + ) + assert memory_contents == expected_memory_contents, ( + ( + "{} bytes of memory contents at base address {}:\n" + "{}\nvs\n{}" + "\nHEXDUMP:\n{}" + "\nvs\n{}" + ).format( + hex(bundle["length"]), + hex(bundle["base_address"]), + memory_contents, + expected_memory_contents, + memory.hexdump(bundle["base_address"], bundle["length"]), + expected_memory.hexdump(bundle["base_address"], bundle["length"]) + ) + ) @cocotb.coroutine async def drive_axi_st(driver, inputs): @@ -128,8 +162,6 @@ async def drive_axi_st(driver, inputs): await driver.send(axi_st_input) def generate_test_data_random(test_count, mem_size): - AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x - addr_req_input = [] axi_st_input = [] addr_resp_expect = [] @@ -154,7 +186,12 @@ def generate_test_data_random(test_count, mem_size): addr_req_input.append(transfer_req) data_to_write = random.randbytes(xfer_len) - axi_st_frame = AxiStreamFrame(tdata=data_to_write, tkeep=[15]*xfer_len, tid=(i % (1 << ID_WIDTH)), tdest=(i % (1 << ID_WIDTH))) + axi_st_frame = axis.AxiStreamFrame( + tdata=data_to_write, + tkeep=[15]*xfer_len, + tid=i % (1 << ID_WIDTH), + tdest=(i % (1 << ID_WIDTH)) + ) axi_st_input.append(axi_st_frame) write_expected_memory(transfer_req, axi_st_frame.tdata, memory) @@ -167,36 +204,48 @@ def generate_test_data_random(test_count, mem_size): addr_resp_expect = [AxiWriterRespStruct(status=False)] * test_count - return (addr_req_input, axi_st_input, addr_resp_expect, memory_verification, memory) + return ( + addr_req_input, + axi_st_input, + addr_resp_expect, + memory_verification, + memory + ) def bytes_to_4k_boundary(addr): - AXI_4K_BOUNDARY = 0x1000 - return AXI_4K_BOUNDARY - (addr % AXI_4K_BOUNDARY) + axi_4k_boundary = 0x1000 + return axi_4k_boundary - (addr % axi_4k_boundary) def write_expected_memory(transfer_req, data_to_write, memory): - """ - Write test data to reference memory keeping the AXI 4kb boundary - by spliting the write requests into smaller ones. - """ - prev_id = 0 - address = transfer_req.address - length = transfer_req.length - - BYTES_IN_TRANSFER = 4 - MAX_AXI_BURST_BYTES = 256 * BYTES_IN_TRANSFER - - while (length > 0): - bytes_to_4k = bytes_to_4k_boundary(address) - new_len = min(length, min(bytes_to_4k, MAX_AXI_BURST_BYTES)) - new_data = data_to_write[prev_id:prev_id+new_len] - memory.write(address, new_data) - address = address + new_len - length = length - new_len - prev_id = prev_id + new_len + """Write test data to reference memory keeping the AXI 4kb boundary. + + Split the write requests into smaller ones as needed. + + Args: + transfer_req: The transfer request object containing address and length + information. + data_to_write: A bytes-like object or list of data that needs to be + written. + memory: SparseMemory object simulating memory storage, where the data will + be written. + """ + prev_id = 0 + address = transfer_req.address + length = transfer_req.length + + bytes_in_transfer = 4 + max_axi_burst_bytes = 256 * bytes_in_transfer + + while (length > 0): + bytes_to_4k = bytes_to_4k_boundary(address) + new_len = min(length, min(bytes_to_4k, max_axi_burst_bytes)) + new_data = data_to_write[prev_id:prev_id+new_len] + memory.write(address, new_data) + address = address + new_len + length = length - new_len + prev_id = prev_id + new_len def generate_test_data_arbitrary(mem_size): - AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x - addr_req_input = [] axi_st_input = [] addr_resp_expect = [] @@ -215,12 +264,21 @@ def generate_test_data_arbitrary(mem_size): addr_req_input.append(transfer_req) data_chunks = [] - data_bytes = [[(0xEF + j) & 0xFF, 0xBE, 0xAD, 0xDE] for j in range(xfer_len[i])] - data_words = [int.from_bytes(data_bytes[j]) for j in range(xfer_len[i])] + data_bytes = [ + [(0xEF + j) & 0xFF, 0xBE, 0xAD, 0xDE] for j in range(xfer_len[i]) + ] + unused_data_words = [ + int.from_bytes(data_bytes[j]) for j in range(xfer_len[i]) + ] for j in range(xfer_len[i]): data_chunks += data_bytes[j] data_to_write = bytearray(data_chunks) - axi_st_frame = AxiStreamFrame(tdata=data_to_write, tkeep=[15]*xfer_len[i], tid=i, tdest=i) + axi_st_frame = axis.AxiStreamFrame( + tdata=data_to_write, + tkeep=[15]*xfer_len[i], + tid=i, + tdest=i + ) axi_st_input.append(axi_st_frame) write_expected_memory(transfer_req, axi_st_frame.tdata, memory) @@ -233,7 +291,13 @@ def generate_test_data_arbitrary(mem_size): addr_resp_expect = [AxiWriterRespStruct(status=False)] * testcase_num - return (addr_req_input, axi_st_input, addr_resp_expect, memory_verification, memory) + return ( + addr_req_input, + axi_st_input, + addr_resp_expect, + memory_verification, + memory + ) if __name__ == "__main__": toplevel = "axi_writer_wrapper" @@ -241,5 +305,5 @@ def generate_test_data_arbitrary(mem_size): "xls/modules/zstd/memory/axi_writer.v", "xls/modules/zstd/memory/rtl/axi_writer_wrapper.v", ] - test_module=[Path(__file__).stem] - run_test(toplevel, test_module, verilog_sources) + test_module=[pathlib.Path(__file__).stem] + utils.run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/mem_reader_cocotb_test.py b/xls/modules/zstd/memory/mem_reader_cocotb_test.py index 3e48904f6a..8f862bc5ca 100644 --- a/xls/modules/zstd/memory/mem_reader_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_reader_cocotb_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright 2024 The XLS Authors # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,26 +13,22 @@ # limitations under the License. +import pathlib import random import sys import warnings -from pathlib import Path import cocotb from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, Event +from cocotb.triggers import Event from cocotb_bus.scoreboard import Scoreboard -from cocotbext.axi.axi_channels import AxiARBus, AxiRBus, AxiReadBus, AxiRTransaction, AxiRSource, AxiRSink, AxiRMonitor +from cocotbext.axi import axi_channels from cocotbext.axi.axi_ram import AxiRamRead from cocotbext.axi.sparse_memory import SparseMemory -from xls.modules.zstd.cocotb.channel import ( - XLSChannel, - XLSChannelDriver, - XLSChannelMonitor, -) -from xls.modules.zstd.cocotb.utils import reset, run_test -from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass +import xls.modules.zstd.cocotb.channel as xlschannel +from xls.modules.zstd.cocotb import utils +from xls.modules.zstd.cocotb import xlsstruct # to disable warnings from hexdiff used by cocotb's Scoreboard warnings.filterwarnings("ignore", category=DeprecationWarning) @@ -60,34 +55,34 @@ # Override default widths of AXI response signals signal_widths = {"rresp": 3, "rlast": 1} -AxiRBus._signal_widths = signal_widths -AxiRTransaction._signal_widths = signal_widths -AxiRSource._signal_widths = signal_widths -AxiRSink._signal_widths = signal_widths -AxiRMonitor._signal_widths = signal_widths - -@xls_dataclass -class MemReaderReq(XLSStruct): +axi_channels.AxiRBus._signal_widths = signal_widths +axi_channels.AxiRTransaction._signal_widths = signal_widths +axi_channels.AxiRSource._signal_widths = signal_widths +axi_channels.AxiRSink._signal_widths = signal_widths +axi_channels.AxiRMonitor._signal_widths = signal_widths + +@xlsstruct.xls_dataclass +class MemReaderReq(xlsstruct.XLSStruct): addr: DSLX_ADDR_W length: DSLX_ADDR_W -@xls_dataclass -class MemReaderResp(XLSStruct): +@xlsstruct.xls_dataclass +class MemReaderResp(xlsstruct.XLSStruct): status: STATUS_W data: DSLX_DATA_W length: DSLX_ADDR_W last: LAST_W -@xls_dataclass -class AxiReaderReq(XLSStruct): +@xlsstruct.xls_dataclass +class AxiReaderReq(xlsstruct.XLSStruct): addr: AXI_ADDR_W len: AXI_ADDR_W -@xls_dataclass -class AxiStream(XLSStruct): +@xlsstruct.xls_dataclass +class AxiStream(xlsstruct.XLSStruct): data: AXI_DATA_W str: AXI_DATA_W // 8 keep: AXI_DATA_W // 8 = 0 @@ -96,13 +91,13 @@ class AxiStream(XLSStruct): dest: DEST_W = 0 -@xls_dataclass -class AxiReaderError(XLSStruct): +@xlsstruct.xls_dataclass +class AxiReaderError(xlsstruct.XLSStruct): error: ERROR_W -@xls_dataclass -class AxiAr(XLSStruct): +@xlsstruct.xls_dataclass +class AxiAr(xlsstruct.XLSStruct): id: ID_W addr: AXI_ADDR_W region: 4 @@ -114,8 +109,8 @@ class AxiAr(XLSStruct): qos: 4 -@xls_dataclass -class AxiR(XLSStruct): +@xlsstruct.xls_dataclass +class AxiR(xlsstruct.XLSStruct): id: ID_W data: AXI_DATA_W resp: 3 @@ -161,11 +156,14 @@ def generate_test_data(test_cases, xfer_base=0x0, seed=1234): req += [MemReaderReq(addr=xfer_addr, length=xfer_length)] rem = xfer_length % data_w_div8 - for addr in range(xfer_addr, xfer_max_addr - (data_w_div8 - 1), data_w_div8): + range_end = xfer_max_addr - (data_w_div8 - 1) + for addr in range(xfer_addr, range_end, data_w_div8): last = ((addr + data_w_div8) >= xfer_max_addr) & (rem == 0) data = random.randint(0, 1 << (data_w_div8 * 8)) mem_writes.update({addr: data}) - resp += [MemReaderResp(status=0, data=data, length=data_w_div8, last=last)] + resp += [ + MemReaderResp(status=0, data=data, length=data_w_div8, last=last) + ] if rem > 0: addr = xfer_max_addr - rem @@ -177,16 +175,27 @@ def generate_test_data(test_cases, xfer_base=0x0, seed=1234): return (req, resp, mem_writes) -async def test_mem_reader(dut, req_input, resp_output, mem_contents={}): +async def test_mem_reader(dut, req_input, resp_output, mem_contents=None): + if mem_contents is None: + mem_contents = {} + clock = Clock(dut.clk, 10, units="us") cocotb.start_soon(clock.start()) - mem_reader_resp_bus = XLSChannel( + # prefix unused objects with unused_ + # to suppress linter and keep the objects alive + unused_mem_reader_resp_bus = xlschannel.XLSChannel( dut, MEM_READER_RESP_CHANNEL, dut.clk, start_now=True ) - mem_reader_req_driver = XLSChannelDriver(dut, MEM_READER_REQ_CHANNEL, dut.clk) - mem_reader_resp_monitor = XLSChannelMonitor( - dut, MEM_READER_RESP_CHANNEL, dut.clk, MemReaderResp, callback=print_callback() + mem_reader_req_driver = xlschannel.XLSChannelDriver( + dut, MEM_READER_REQ_CHANNEL, dut.clk + ) + mem_reader_resp_monitor = xlschannel.XLSChannelMonitor( + dut, + MEM_READER_RESP_CHANNEL, + dut.clk, + MemReaderResp, + callback=print_callback() ) terminate = Event() @@ -195,18 +204,20 @@ async def test_mem_reader(dut, req_input, resp_output, mem_contents={}): scoreboard = Scoreboard(dut) scoreboard.add_interface(mem_reader_resp_monitor, resp_output) - ar_bus = AxiARBus.from_prefix(dut, AXI_AR_PREFIX) - r_bus = AxiRBus.from_prefix(dut, AXI_R_PREFIX) - axi_read_bus = AxiReadBus(ar=ar_bus, r=r_bus) + ar_bus = axi_channels.AxiARBus.from_prefix(dut, AXI_AR_PREFIX) + r_bus = axi_channels.AxiRBus.from_prefix(dut, AXI_R_PREFIX) + axi_read_bus = axi_channels.AxiReadBus(ar=ar_bus, r=r_bus) mem_size = 2**AXI_ADDR_W sparse_mem = SparseMemory(mem_size) for addr, data in mem_contents.items(): sparse_mem.write(addr, (data).to_bytes(8, "little")) - memory = AxiRamRead(axi_read_bus, dut.clk, dut.rst, size=mem_size, mem=sparse_mem) + unused_memory = AxiRamRead( + axi_read_bus, dut.clk, dut.rst, size=mem_size, mem=sparse_mem + ) - await reset(dut.clk, dut.rst, cycles=10) + await utils.reset(dut.clk, dut.rst, cycles=10) await mem_reader_req_driver.send(req_input) await terminate.wait() @@ -260,12 +271,12 @@ async def mem_reader_aligned_transfer_shorter_than_bus4(dut): if __name__ == "__main__": - sys.path.append(str(Path(__file__).parent)) + sys.path.append(str(pathlib.Path(__file__).parent)) toplevel = "mem_reader_wrapper" verilog_sources = [ "xls/modules/zstd/memory/mem_reader_adv.v", "xls/modules/zstd/memory/rtl/mem_reader_wrapper.v", ] - test_module = [Path(__file__).stem] - run_test(toplevel, test_module, verilog_sources) + test_module = [pathlib.Path(__file__).stem] + utils.run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/mem_writer_cocotb_test.py b/xls/modules/zstd/memory/mem_writer_cocotb_test.py index 69b39a7894..5767fbba2e 100644 --- a/xls/modules/zstd/memory/mem_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_writer_cocotb_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright 2024 The XLS Authors # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,60 +15,54 @@ import random import logging -from enum import Enum -from pathlib import Path +import enum +import pathlib import cocotb from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, Event -from cocotb.binary import BinaryValue +from cocotb.triggers import Event from cocotb_bus.scoreboard import Scoreboard -from cocotbext.axi.axis import AxiStreamSource, AxiStreamBus, AxiStreamFrame -from cocotbext.axi.axi_channels import AxiAWBus, AxiWBus, AxiBBus, AxiWriteBus, AxiAWMonitor, AxiWMonitor, AxiBMonitor, AxiBTransaction, AxiBSource, AxiBSink +from cocotbext.axi import axi_channels from cocotbext.axi.axi_ram import AxiRamWrite from cocotbext.axi.sparse_memory import SparseMemory -from xls.modules.zstd.cocotb.channel import ( - XLSChannel, - XLSChannelDriver, - XLSChannelMonitor, -) -from xls.modules.zstd.cocotb.utils import reset, run_test -from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass +import xls.modules.zstd.cocotb.channel as xlschannel +from xls.modules.zstd.cocotb import utils +from xls.modules.zstd.cocotb import xlsstruct DATA_WIDTH = 32 ADDR_WIDTH = 16 # Override default widths of AXI response signals signal_widths = {"bresp": 3} -AxiBBus._signal_widths = signal_widths -AxiBTransaction._signal_widths = signal_widths -AxiBSource._signal_widths = signal_widths -AxiBSink._signal_widths = signal_widths -AxiBMonitor._signal_widths = signal_widths - -@xls_dataclass -class DataInStruct(XLSStruct): +axi_channels.AxiBBus._signal_widths = signal_widths +axi_channels.AxiBTransaction._signal_widths = signal_widths +axi_channels.AxiBSource._signal_widths = signal_widths +axi_channels.AxiBSink._signal_widths = signal_widths +axi_channels.AxiBMonitor._signal_widths = signal_widths + +@xlsstruct.xls_dataclass +class DataInStruct(xlsstruct.XLSStruct): data: DATA_WIDTH length: ADDR_WIDTH last: 1 -@xls_dataclass -class WriteReqStruct(XLSStruct): +@xlsstruct.xls_dataclass +class WriteReqStruct(xlsstruct.XLSStruct): offset: ADDR_WIDTH length: ADDR_WIDTH -@xls_dataclass -class MemWriterRespStruct(XLSStruct): +@xlsstruct.xls_dataclass +class MemWriterRespStruct(xlsstruct.XLSStruct): status: 1 -class MemWriterRespStatus(Enum): +class MemWriterRespStatus(enum.Enum): OKAY = 0 ERROR = 1 -@xls_dataclass -class WriteRequestStruct(XLSStruct): +@xlsstruct.xls_dataclass +class WriteRequestStruct(xlsstruct.XLSStruct): address: ADDR_WIDTH length: ADDR_WIDTH @@ -79,13 +72,22 @@ def terminate_cb(_): event.set() monitor.add_callback(terminate_cb) -async def test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt): - GENERIC_WRITE_REQ_CHANNEL = "req" - GENERIC_WRITE_RESP_CHANNEL = "resp" - GENERIC_DATA_IN_CHANNEL = "data_in" - AXI_AW_CHANNEL = "axi_aw" - AXI_W_CHANNEL = "axi_w" - AXI_B_CHANNEL = "axi_b" +async def test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt +): + generic_write_req_channel = "req" + generic_write_resp_channel = "resp" + generic_data_in_channel = "data_in" + axi_aw_channel = "axi_aw" + axi_w_channel = "axi_w" + axi_b_channel = "axi_b" terminate = Event() @@ -94,22 +96,38 @@ async def test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_ clock = Clock(dut.clk, 10, units="us") cocotb.start_soon(clock.start()) - resp_bus = XLSChannel(dut, GENERIC_WRITE_RESP_CHANNEL, dut.clk, start_now=True) - - driver_write_req = XLSChannelDriver(dut, GENERIC_WRITE_REQ_CHANNEL, dut.clk) - driver_data_in = XLSChannelDriver(dut, GENERIC_DATA_IN_CHANNEL, dut.clk) - - bus_axi_aw = AxiAWBus.from_prefix(dut, AXI_AW_CHANNEL) - bus_axi_w = AxiWBus.from_prefix(dut, AXI_W_CHANNEL) - bus_axi_b = AxiBBus.from_prefix(dut, AXI_B_CHANNEL) - bus_axi_write = AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) - - monitor_write_req = XLSChannelMonitor(dut, GENERIC_WRITE_REQ_CHANNEL, dut.clk, WriteRequestStruct) - monitor_data_in = XLSChannelMonitor(dut, GENERIC_DATA_IN_CHANNEL, dut.clk, WriteRequestStruct) - monitor_write_resp = XLSChannelMonitor(dut, GENERIC_WRITE_RESP_CHANNEL, dut.clk, MemWriterRespStruct) - monitor_axi_aw = AxiAWMonitor(bus_axi_aw, dut.clk, dut.rst) - monitor_axi_w = AxiWMonitor(bus_axi_w, dut.clk, dut.rst) - monitor_axi_b = AxiBMonitor(bus_axi_b, dut.clk, dut.rst) + # prefix unused objects with unused_ + # to suppress linter and keep the objects alive + unused_resp_bus = xlschannel.XLSChannel( + dut, generic_write_resp_channel, dut.clk, start_now=True + ) + + driver_write_req = xlschannel.XLSChannelDriver( + dut, generic_write_req_channel, dut.clk + ) + driver_data_in = xlschannel.XLSChannelDriver( + dut, generic_data_in_channel, dut.clk + ) + + bus_axi_aw = axi_channels.AxiAWBus.from_prefix(dut, axi_aw_channel) + bus_axi_w = axi_channels.AxiWBus.from_prefix(dut, axi_w_channel) + bus_axi_b = axi_channels.AxiBBus.from_prefix(dut, axi_b_channel) + bus_axi_write = axi_channels.AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) + + unused_monitor_write_req = xlschannel.XLSChannelMonitor( + dut, generic_write_req_channel, dut.clk, WriteRequestStruct + ) + unused_monitor_data_in = xlschannel.XLSChannelMonitor( + dut, generic_data_in_channel, dut.clk, WriteRequestStruct + ) + monitor_write_resp = xlschannel.XLSChannelMonitor( + dut, generic_write_resp_channel, dut.clk, MemWriterRespStruct + ) + unused_monitor_axi_aw = axi_channels.AxiAWMonitor( + bus_axi_aw, dut.clk, dut.rst + ) + unused_monitor_axi_w = axi_channels.AxiWMonitor(bus_axi_w, dut.clk, dut.rst) + unused_monitor_axi_b = axi_channels.AxiBMonitor(bus_axi_b, dut.clk, dut.rst) set_termination_event(monitor_write_resp, terminate, resp_cnt) @@ -122,98 +140,323 @@ async def test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_ scoreboard = Scoreboard(dut) scoreboard.add_interface(monitor_write_resp, write_resp_expect) - await reset(dut.clk, dut.rst, cycles=10) + await utils.reset(dut.clk, dut.rst, cycles=10) await cocotb.start(driver_write_req.send(write_req_input)) await cocotb.start(driver_data_in.send(data_in_input)) await terminate.wait() for bundle in memory_verification: - memory_contents = bytearray(memory.read(bundle["base_address"], bundle["length"])) - expected_memory_contents = bytearray(expected_memory.read(bundle["base_address"], bundle["length"])) - assert memory_contents == expected_memory_contents, "{} bytes of memory contents at base address {}:\n{}\nvs\n{}\nHEXDUMP:\n{}\nvs\n{}".format(hex(bundle["length"]), hex(bundle["base_address"]), memory_contents, expected_memory_contents, memory.hexdump(bundle["base_address"], bundle["length"]), expected_memory.hexdump(bundle["base_address"], bundle["length"])) + memory_contents = bytearray( + memory.read(bundle["base_address"], bundle["length"]) + ) + expected_memory_contents = bytearray( + expected_memory.read(bundle["base_address"], bundle["length"]) + ) + assert memory_contents == expected_memory_contents, ( + ( + "{} bytes of memory contents at base address {}:\n" + "{}\nvs\n{}" + "\nHEXDUMP:\n{}" + "\nvs\n{}" + ).format( + hex(bundle["length"]), + hex(bundle["base_address"]), + memory_contents, + expected_memory_contents, + memory.hexdump(bundle["base_address"], bundle["length"]), + expected_memory.hexdump(bundle["base_address"], bundle["length"]) + ) + ) @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_single_burst_1_transfer(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_1_transfer) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_1_transfer) + + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_single_burst_2_transfers(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_2_transfers) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, test_cases_single_burst_2_transfers + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_single_burst_almost_max_burst_transfer(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_almost_max_burst_transfer) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, test_cases_single_burst_almost_max_burst_transfer + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_single_burst_max_burst_transfer(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_single_burst_max_burst_transfer) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, test_cases_single_burst_max_burst_transfer + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_multiburst_2_full_bursts(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_2_full_bursts) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, test_cases_multiburst_2_full_bursts + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_multiburst_1_full_burst_and_single_transfer(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_1_full_burst_and_single_transfer) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, test_cases_multiburst_1_full_burst_and_single_transfer + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") async def ram_test_multiburst_crossing_4kb_boundary(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_crossing_4kb_boundary) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, test_cases_multiburst_crossing_4kb_boundary + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") -async def ram_test_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts(dut): +async def ram_test_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts( + dut, +): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, + test_cases_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts, + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=2000, timeout_unit="ms") -async def ram_test_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer(dut): +async def ram_test_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer( + dut, +): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_arbitrary(mem_size, test_cases_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_test_data_arbitrary( + mem_size, + test_cases_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer, + ) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=5000, timeout_unit="ms") async def ram_test_not_full_packets(dut): mem_size = 2**ADDR_WIDTH - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_padded_test_data_arbitrary(mem_size, test_cases_not_full_packets) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) = generate_padded_test_data_arbitrary(mem_size, test_cases_not_full_packets) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt, + ) + @cocotb.test(timeout_time=5000, timeout_unit="ms") async def ram_test_random(dut): mem_size = 2**ADDR_WIDTH test_count = 50 - (write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) = generate_test_data_random(test_count, mem_size) - await test_writer(dut, mem_size, write_req_input, data_in_input, write_resp_expect, memory_verification, expected_memory, resp_cnt) + ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt + ) = generate_test_data_random(test_count, mem_size) + await test_writer( + dut, + mem_size, + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + expected_memory, + resp_cnt + ) def generate_test_data_random(test_count, mem_size): - AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x - write_req_input = [] data_in_input = [] write_resp_expect = [] @@ -224,7 +467,7 @@ def generate_test_data_random(test_count, mem_size): xfer_baseaddr = 0 - for i in range(test_count): + for _ in range(test_count): # Generate offset from the absolute address max_xfer_offset = mem_size - xfer_baseaddr xfer_offset = random.randrange(0, max_xfer_offset) @@ -272,37 +515,51 @@ def generate_test_data_random(test_count, mem_size): } memory_verification.append(memory_bundle) - write_resp_expect = [MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value)] * test_count + write_resp_expect = [ + MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value) + ] * test_count - return (write_req_input, data_in_input, write_resp_expect, memory_verification, memory, test_count) + return ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + memory, + test_count + ) def bytes_to_4k_boundary(addr): - AXI_4K_BOUNDARY = 0x1000 - return AXI_4K_BOUNDARY - (addr % AXI_4K_BOUNDARY) + axi_4k_boundary = 0x1000 + return axi_4k_boundary - (addr % axi_4k_boundary) def write_expected_memory(transfer_req, data_to_write, memory): - """ - Write test data to reference memory keeping the AXI 4kb boundary - by spliting the write requests into smaller ones. - """ - prev_id = 0 - address = transfer_req.address - length = transfer_req.length - - BYTES_IN_TRANSFER = 4 - MAX_AXI_BURST_BYTES = 256 * BYTES_IN_TRANSFER - - while (length > 0): - bytes_to_4k = bytes_to_4k_boundary(address) - new_len = min(length, min(bytes_to_4k, MAX_AXI_BURST_BYTES)) - new_data = data_to_write[prev_id:prev_id+new_len] - memory.write(address, new_data) - address = address + new_len - length = length - new_len - prev_id = prev_id + new_len + """ + Write test data to reference memory keeping the AXI 4kb boundary. + + Split the write requests into smaller ones as needed. + + Args: + transfer_req: The transfer request object containing address and length information. + data_to_write: A bytes-like object or list of data that needs to be written. + memory: SparseMemory object simulating memory storage, where the data will be written. + """ + prev_id = 0 + address = transfer_req.address + length = transfer_req.length + + bytes_in_transfer = 4 + max_axi_burst_bytes = 256 * bytes_in_transfer + + while (length > 0): + bytes_to_4k = bytes_to_4k_boundary(address) + new_len = min(length, min(bytes_to_4k, max_axi_burst_bytes)) + new_data = data_to_write[prev_id:prev_id+new_len] + memory.write(address, new_data) + address = address + new_len + length = length - new_len + prev_id = prev_id + new_len def generate_test_data_arbitrary(mem_size, test_cases): - AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x test_count = len(test_cases) random.seed(1234) @@ -364,12 +621,20 @@ def generate_test_data_arbitrary(mem_size, test_cases): } memory_verification.append(memory_bundle) - write_resp_expect = [MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value)] * test_count + write_resp_expect = [ + MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value) + ] * test_count - return (write_req_input, data_in_input, write_resp_expect, memory_verification, memory, test_count) + return ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + memory, + test_count + ) def generate_padded_test_data_arbitrary(mem_size, test_cases): - AXI_AXSIZE_ENCODING_MAX_4B_TRANSFER = 2 # Must be in sync with AXI_AXSIZE_ENCODING enum in axi.x test_count = len(test_cases) random.seed(1234) @@ -412,9 +677,12 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): last = packet_len == bytes_to_packetize data_in = DataInStruct( - data = int.from_bytes(data_to_write[packetized_bytes:packetized_bytes+packet_len], byteorder='little'), - length = packet_len, - last = last + data=int.from_bytes( + data_to_write[packetized_bytes:packetized_bytes+packet_len], + byteorder='little' + ), + length=packet_len, + last=last ) data_in_input.append(data_in) @@ -435,9 +703,18 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): } memory_verification.append(memory_bundle) - write_resp_expect = [MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value)] * test_count + write_resp_expect = [ + MemWriterRespStruct(status=MemWriterRespStatus.OKAY.value) + ] * test_count - return (write_req_input, data_in_input, write_resp_expect, memory_verification, memory, test_count) + return ( + write_req_input, + data_in_input, + write_resp_expect, + memory_verification, + memory, + test_count + ) if __name__ == "__main__": toplevel = "mem_writer_wrapper" @@ -445,8 +722,8 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): "xls/modules/zstd/memory/mem_writer.v", "xls/modules/zstd/memory/rtl/mem_writer_wrapper.v", ] - test_module=[Path(__file__).stem] - run_test(toplevel, test_module, verilog_sources) + test_module=[pathlib.Path(__file__).stem] + utils.run_test(toplevel, test_module, verilog_sources) test_cases_single_burst_1_transfer = [ # Aligned Address; Aligned Length @@ -611,9 +888,11 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): ] test_cases_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts = [ - # Aligned Address; Aligned Length; Multi-Burst; crossing 4kB boundary with perfectly aligned full bursts + # Aligned Address; Aligned Length; Multi-Burst; + # crossing 4kB boundary with perfectly aligned full bursts (0x0C00, 0x800), - # Unaligned Address; Unaligned Length; Multi-Burst; crossing 4kB boundary with perfectly aligned full bursts + # Unaligned Address; Unaligned Length; Multi-Burst; + # crossing 4kB boundary with perfectly aligned full bursts (0x1C01, 0x7FF), (0x2C02, 0x7FE), (0x3C03, 0x7FD), diff --git a/xls/modules/zstd/memory/rtl/mem_reader_wrapper.v b/xls/modules/zstd/memory/rtl/mem_reader_wrapper.v index 0dfd2dd941..12e1fe4478 100644 --- a/xls/modules/zstd/memory/rtl/mem_reader_wrapper.v +++ b/xls/modules/zstd/memory/rtl/mem_reader_wrapper.v @@ -18,18 +18,18 @@ `default_nettype none module mem_reader_wrapper #( - parameter DSLX_DATA_W = 64, - parameter DSLX_ADDR_W = 16, - parameter AXI_DATA_W = 128, - parameter AXI_ADDR_W = 16, - parameter AXI_DEST_W = 8, - parameter AXI_ID_W = 8, - - parameter CTRL_W = (DSLX_ADDR_W), - parameter REQ_W = (2 * DSLX_ADDR_W), - parameter RESP_W = (1 + DSLX_DATA_W + DSLX_ADDR_W + 1), - parameter AXI_AR_W = (AXI_ID_W + AXI_ADDR_W + 28), - parameter AXI_R_W = (AXI_ID_W + AXI_DATA_W + 4) + parameter int DSLX_DATA_W = 64, + parameter int DSLX_ADDR_W = 16, + parameter int AXI_DATA_W = 128, + parameter int AXI_ADDR_W = 16, + parameter int AXI_DEST_W = 8, + parameter int AXI_ID_W = 8, + + parameter int CTRL_W = (DSLX_ADDR_W), + parameter int REQ_W = (2 * DSLX_ADDR_W), + parameter int RESP_W = (1 + DSLX_DATA_W + DSLX_ADDR_W + 1), + parameter int AXI_AR_W = (AXI_ID_W + AXI_ADDR_W + 28), + parameter int AXI_R_W = (AXI_ID_W + AXI_DATA_W + 4) ) ( input wire clk, input wire rst, diff --git a/xls/modules/zstd/memory/rtl/mem_writer_wrapper.v b/xls/modules/zstd/memory/rtl/mem_writer_wrapper.v index 958383c282..6b53dbd805 100644 --- a/xls/modules/zstd/memory/rtl/mem_writer_wrapper.v +++ b/xls/modules/zstd/memory/rtl/mem_writer_wrapper.v @@ -125,40 +125,70 @@ module mem_writer_wrapper ( wire [ 0:0] axi_stream_padded_tvalid; wire [ 0:0] axi_stream_padded_tready; - assign {axi_writer_write_req_address, axi_writer_write_req_length} = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_writer_req_data; - assign axi_writer_write_req_valid = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_writer_req_vld; - assign axi_writer_write_req_ready = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_writer_req_rdy; - - assign {padding_write_req_address, padding_write_req_length} = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__padding_req_data; - assign padding_write_req_valid = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__padding_req_vld; - assign padding_write_req_ready = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__padding_req_rdy; + assign {axi_writer_write_req_address, axi_writer_write_req_length} = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__axi_writer_req_data; + assign axi_writer_write_req_valid = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__axi_writer_req_vld; + assign axi_writer_write_req_ready = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__axi_writer_req_rdy; + + assign {padding_write_req_address, padding_write_req_length} = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__padding_req_data; + assign padding_write_req_valid = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__padding_req_vld; + assign padding_write_req_ready = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__padding_req_rdy; assign { axi_stream_raw_tdata, axi_stream_raw_tstr, axi_stream_raw_tkeep, axi_stream_raw_tid, axi_stream_raw_tdest, - axi_stream_raw_tlast} = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_st_raw_data; - assign axi_stream_raw_tvalid = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_st_raw_vld; - assign axi_stream_raw_tready = mem_writer.__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0.mem_writer__axi_st_raw_rdy; + axi_stream_raw_tlast} = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__axi_st_raw_data; + assign axi_stream_raw_tvalid = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__axi_st_raw_vld; + assign axi_stream_raw_tready = mem_writer + .__mem_writer__MemWriterInst__MemWriter_0__MemWriterInternal_0__16_32_4_4_4_2_next_inst0 + .mem_writer__axi_st_raw_rdy; assign { axi_stream_clean_tdata, axi_stream_clean_tstr, axi_stream_clean_tkeep, axi_stream_clean_tid, axi_stream_clean_tdest, - axi_stream_clean_tlast} = mem_writer.__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1.mem_writer__axi_st_clean_data; - assign axi_stream_clean_tvalid = mem_writer.__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1.mem_writer__axi_st_clean_vld; - assign axi_stream_clean_tready = mem_writer.__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1.mem_writer__axi_st_clean_rdy; + axi_stream_clean_tlast} = mem_writer + .__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1 // verilog_lint: waive line-length + .mem_writer__axi_st_clean_data; + assign axi_stream_clean_tvalid = mem_writer + .__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1 // verilog_lint: waive line-length + .mem_writer__axi_st_clean_vld; + assign axi_stream_clean_tready = mem_writer + .__xls_modules_zstd_memory_axi_stream_add_empty__MemWriterInst__MemWriter_0__AxiStreamAddEmpty_0__16_32_4_2_4_4_next_inst1 // verilog_lint: waive line-length + .mem_writer__axi_st_clean_rdy; assign { axi_stream_padded_tdata, axi_stream_padded_tstr, axi_stream_padded_tkeep, axi_stream_padded_tid, axi_stream_padded_tdest, - axi_stream_padded_tlast} = mem_writer.__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4.mem_writer__axi_st_padded_data; - assign axi_stream_padded_tvalid = mem_writer.__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4.mem_writer__axi_st_padded_vld; - assign axi_stream_padded_tready = mem_writer.__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4.mem_writer__axi_st_padded_rdy; + axi_stream_padded_tlast} = mem_writer + .__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4 // verilog_lint: waive line-length + .mem_writer__axi_st_padded_data; + assign axi_stream_padded_tvalid = mem_writer + .__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4 // verilog_lint: waive line-length + .mem_writer__axi_st_padded_vld; + assign axi_stream_padded_tready = mem_writer + .__xls_modules_zstd_memory_axi_writer__MemWriterInst__MemWriter_0__AxiWriter_0__16_32_4_4_4_2_next_inst4 // verilog_lint: waive line-length + .mem_writer__axi_st_padded_rdy; mem_writer mem_writer ( .clk(clk), diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index a5ca1daec6..e608e9b6f2 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright 2024 The XLS Authors # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,31 +13,23 @@ # limitations under the License. -from enum import Enum -from pathlib import Path +import enum +import pathlib import tempfile import cocotb +from cocotb import triggers from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, Event -from cocotb.binary import BinaryValue -from cocotb_bus.scoreboard import Scoreboard +from cocotbext.axi import axi_channels from cocotbext.axi.axi_master import AxiMaster -from cocotbext.axi.axi_channels import AxiAWBus, AxiWBus, AxiBBus, AxiWriteBus, AxiARBus, AxiRBus, AxiReadBus, AxiBus, AxiBTransaction, AxiBSource, AxiBSink, AxiBMonitor, AxiRTransaction, AxiRSource, AxiRSink, AxiRMonitor -from cocotbext.axi.axi_ram import AxiRam from cocotbext.axi.sparse_memory import SparseMemory -from xls.common import runfiles -from xls.modules.zstd.cocotb.channel import ( - XLSChannel, - XLSChannelDriver, - XLSChannelMonitor, -) -from xls.modules.zstd.cocotb.data_generator import GenerateFrame, DecompressFrame, BlockType -from xls.modules.zstd.cocotb.memory import init_axi_mem, AxiRamFromFile -from xls.modules.zstd.cocotb.utils import reset, run_test -from xls.modules.zstd.cocotb.xlsstruct import XLSStruct, xls_dataclass +import xls.modules.zstd.cocotb.channel as xlschannel +from xls.modules.zstd.cocotb import data_generator +from xls.modules.zstd.cocotb.memory import AxiRamFromFile +from xls.modules.zstd.cocotb.utils import run_test +from xls.modules.zstd.cocotb import xlsstruct AXI_DATA_W = 64 AXI_DATA_W_BYTES = AXI_DATA_W // 8 @@ -48,34 +39,34 @@ # Override default widths of AXI response signals signal_widths = {"bresp": 3} -AxiBBus._signal_widths = signal_widths -AxiBTransaction._signal_widths = signal_widths -AxiBSource._signal_widths = signal_widths -AxiBSink._signal_widths = signal_widths -AxiBMonitor._signal_widths = signal_widths +axi_channels.AxiBBus._signal_widths = signal_widths +axi_channels.AxiBTransaction._signal_widths = signal_widths +axi_channels.AxiBSource._signal_widths = signal_widths +axi_channels.AxiBSink._signal_widths = signal_widths +axi_channels.AxiBMonitor._signal_widths = signal_widths signal_widths = {"rresp": 3, "rlast": 1} -AxiRBus._signal_widths = signal_widths -AxiRTransaction._signal_widths = signal_widths -AxiRSource._signal_widths = signal_widths -AxiRSink._signal_widths = signal_widths -AxiRMonitor._signal_widths = signal_widths - -@xls_dataclass -class NotifyStruct(XLSStruct): +axi_channels.AxiRBus._signal_widths = signal_widths +axi_channels.AxiRTransaction._signal_widths = signal_widths +axi_channels.AxiRSource._signal_widths = signal_widths +axi_channels.AxiRSink._signal_widths = signal_widths +axi_channels.AxiRMonitor._signal_widths = signal_widths + +@xlsstruct.xls_dataclass +class NotifyStruct(xlsstruct.XLSStruct): pass -class CSR(Enum): +class CSR(enum.Enum): """ - Maps the offsets to the ZSTD Decoder registers + Maps the offsets to the ZSTD Decoder registers. """ - Status = 0 - Start = 1 - InputBuffer = 2 - OutputBuffer = 3 + STATUS = 0 + START = 1 + INPUTBUFFER = 2 + OUTPUTBUFFER = 3 -class Status(Enum): +class Status(enum.Enum): """ - Codes for the Status register + Codes for the Status register. """ IDLE = 0x0 RUNNING = 0x1 @@ -87,39 +78,39 @@ def terminate_cb(_): monitor.add_callback(terminate_cb) def connect_axi_read_bus(dut, name=""): - AXI_AR = "axi_ar" - AXI_R = "axi_r" + axi_ar = "axi_ar" + axi_r = "axi_r" - if name != "": + if name: name += "_" - bus_axi_ar = AxiARBus.from_prefix(dut, name + AXI_AR) - bus_axi_r = AxiRBus.from_prefix(dut, name + AXI_R) + bus_axi_ar = axi_channels.AxiARBus.from_prefix(dut, name + axi_ar) + bus_axi_r = axi_channels.AxiRBus.from_prefix(dut, name + axi_r) - return AxiReadBus(bus_axi_ar, bus_axi_r) + return axi_channels.AxiReadBus(bus_axi_ar, bus_axi_r) def connect_axi_write_bus(dut, name=""): - AXI_AW = "axi_aw" - AXI_W = "axi_w" - AXI_B = "axi_b" + axi_aw = "axi_aw" + axi_w = "axi_w" + axi_b = "axi_b" - if name != "": + if name: name += "_" - bus_axi_aw = AxiAWBus.from_prefix(dut, name + AXI_AW) - bus_axi_w = AxiWBus.from_prefix(dut, name + AXI_W) - bus_axi_b = AxiBBus.from_prefix(dut, name + AXI_B) + bus_axi_aw = axi_channels.AxiAWBus.from_prefix(dut, name + axi_aw) + bus_axi_w = axi_channels.AxiWBus.from_prefix(dut, name + axi_w) + bus_axi_b = axi_channels.AxiBBus.from_prefix(dut, name + axi_b) - return AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) + return axi_channels.AxiWriteBus(bus_axi_aw, bus_axi_w, bus_axi_b) def connect_axi_bus(dut, name=""): bus_axi_read = connect_axi_read_bus(dut, name) bus_axi_write = connect_axi_write_bus(dut, name) - return AxiBus(bus_axi_write, bus_axi_read) + return axi_channels.AxiBus(bus_axi_write, bus_axi_read) async def csr_write(cpu, csr, data): - if type(data) is int: + if isinstance(data, int): data = data.to_bytes(AXI_DATA_W_BYTES, byteorder='little') assert len(data) <= AXI_DATA_W_BYTES await cpu.write(csr.value * AXI_DATA_W_BYTES, data) @@ -138,7 +129,7 @@ async def test_csr(dut): cpu = AxiMaster(csr_bus, dut.clk, dut.rst) - await ClockCycles(dut.clk, 10) + await triggers.ClockCycles(dut.clk, 10) i = 0 for reg in CSR: expected_src = bytearray.fromhex("0DF0AD8BEFBEADDE") @@ -147,9 +138,11 @@ async def test_csr(dut): expected[0] += i await csr_write(cpu, reg, expected) read = await csr_read(cpu, reg) - assert read.data == expected, "Expected data doesn't match contents of the {}".format(reg) + assert read.data == expected, ( + "Expected data doesn't match contents of the {}".format(reg) + ) i += 1 - await ClockCycles(dut.clk, 10) + await triggers.ClockCycles(dut.clk, 10) async def test_reset(dut): clock = Clock(dut.clk, 10, units="us") @@ -160,47 +153,49 @@ async def test_reset(dut): csr_bus = connect_axi_bus(dut, "csr") cpu = AxiMaster(csr_bus, dut.clk, dut.rst) - await ClockCycles(dut.clk, 10) + await triggers.ClockCycles(dut.clk, 10) await start_decoder(cpu) timeout = 10 - status = await csr_read(cpu, CSR.Status) - while ((int.from_bytes(status.data, byteorder='little') == Status.IDLE.value) & (timeout != 0)): - status = await csr_read(cpu, CSR.Status) + status = await csr_read(cpu, CSR.STATUS) + while ((int.from_bytes(status.data, byteorder='little') == Status.IDLE.value) + & (timeout != 0)): + status = await csr_read(cpu, CSR.STATUS) timeout -= 1 assert (timeout != 0) await reset_dut(dut, 50) await wait_for_idle(cpu, 10) - await ClockCycles(dut.clk, 10) + await triggers.ClockCycles(dut.clk, 10) -async def configure_decoder(cpu, ibuf_addr, obuf_addr): - status = await csr_read(cpu, CSR.Status) +async def configure_decoder(dut, cpu, ibuf_addr, obuf_addr): + status = await csr_read(cpu, CSR.STATUS) if int.from_bytes(status.data, byteorder='little') != Status.IDLE.value: await reset_dut(dut, 50) - await csr_write(cpu, CSR.InputBuffer, ibuf_addr) - await csr_write(cpu, CSR.OutputBuffer, obuf_addr) + await csr_write(cpu, CSR.INPUTBUFFER, ibuf_addr) + await csr_write(cpu, CSR.OUTPUTBUFFER, obuf_addr) async def start_decoder(cpu): - await csr_write(cpu, CSR.Start, 0x1) + await csr_write(cpu, CSR.START, 0x1) async def wait_for_idle(cpu, timeout=100): - status = await csr_read(cpu, CSR.Status) - while ((int.from_bytes(status.data, byteorder='little') != Status.IDLE.value) & (timeout != 0)): - status = await csr_read(cpu, CSR.Status) + status = await csr_read(cpu, CSR.STATUS) + while ((int.from_bytes(status.data, byteorder='little') != Status.IDLE.value) + & (timeout != 0)): + status = await csr_read(cpu, CSR.STATUS) timeout -= 1 assert (timeout != 0) async def reset_dut(dut, rst_len=10): dut.rst.setimmediatevalue(0) - await ClockCycles(dut.clk, rst_len) + await triggers.ClockCycles(dut.clk, rst_len) dut.rst.setimmediatevalue(1) - await ClockCycles(dut.clk, rst_len) + await triggers.ClockCycles(dut.clk, rst_len) dut.rst.setimmediatevalue(0) def connect_xls_channel(dut, channel_name, xls_struct): - channel = XLSChannel(dut, channel_name, dut.clk, start_now=True) - monitor = XLSChannelMonitor(dut, channel_name, dut.clk, xls_struct) + channel = xlschannel.XLSChannel(dut, channel_name, dut.clk, start_now=True) + monitor = xlschannel.XLSChannelMonitor(dut, channel_name, dut.clk, xls_struct) return (channel, monitor) @@ -221,10 +216,11 @@ def prepare_test_environment(dut): async def test_decoder(dut, seed, block_type, axi_buses, cpu): memory_bus = axi_buses["memory"] - csr_bus = axi_buses["csr"] - (notify_channel, notify_monitor) = connect_xls_channel(dut, NOTIFY_CHANNEL, NotifyStruct) - assert_notify = Event() + (unused_notify_channel, notify_monitor) = connect_xls_channel( + dut, NOTIFY_CHANNEL, NotifyStruct + ) + assert_notify = triggers.Event() set_termination_event(notify_monitor, assert_notify, 1) mem_size = MAX_ENCODED_FRAME_SIZE_B @@ -236,31 +232,55 @@ async def test_decoder(dut, seed, block_type, axi_buses, cpu): await reset_dut(dut, 50) # Generate ZSTD frame to temporary file - GenerateFrame(seed, block_type, encoded.name) + data_generator.GenerateFrame(seed, block_type, encoded.name) - expected_decoded_frame = DecompressFrame(encoded.read()) + expected_decoded_frame = data_generator.DecompressFrame(encoded.read()) encoded.close() reference_memory = SparseMemory(mem_size) reference_memory.write(obuf_addr, expected_decoded_frame) # Initialise testbench memory with generated ZSTD frame - memory = AxiRamFromFile(bus=memory_bus, clock=dut.clk, reset=dut.rst, path=encoded.name, size=mem_size) - - await configure_decoder(cpu, ibuf_addr, obuf_addr) + memory = AxiRamFromFile( + bus=memory_bus, + clock=dut.clk, + reset=dut.rst, + path=encoded.name, + size=mem_size + ) + + await configure_decoder(dut, cpu, ibuf_addr, obuf_addr) await start_decoder(cpu) await assert_notify.wait() await wait_for_idle(cpu) # Read decoded frame in chunks of AXI_DATA_W length # Compare against frame decompressed with the reference library - for read_op in range(0, ((len(expected_decoded_frame) + (AXI_DATA_W_BYTES - 1)) // AXI_DATA_W_BYTES)): + chunks_nb = ( + len(expected_decoded_frame) + (AXI_DATA_W_BYTES - 1) + ) // AXI_DATA_W_BYTES + for read_op in range(0, chunks_nb): addr = obuf_addr + (read_op * AXI_DATA_W_BYTES) mem_contents = memory.read(addr, AXI_DATA_W_BYTES) exp_mem_contents = reference_memory.read(addr, AXI_DATA_W_BYTES) - assert mem_contents == exp_mem_contents, "{} bytes of memory contents at address {} don't match the expected contents:\n{}\nvs\n{}".format(AXI_DATA_W_BYTES, hex(addr), hex(int.from_bytes(mem_contents, byteorder='little')), hex(int.from_bytes(exp_mem_contents, byteorder='little'))) - - await ClockCycles(dut.clk, 20) - -async def testing_routine(dut, test_cases=1, block_type=BlockType.RANDOM): + assert mem_contents == exp_mem_contents, ( + ( + "{} bytes of memory contents at address {} " + "don't match the expected contents:\n" + "{}\nvs\n{}" + ).format( + AXI_DATA_W_BYTES, + hex(addr), + hex(int.from_bytes(mem_contents, byteorder='little')), + hex(int.from_bytes(exp_mem_contents, byteorder='little')) + ) + ) + + await triggers.ClockCycles(dut.clk, 20) + +async def testing_routine( + dut, + test_cases=1, + block_type=data_generator.BlockType.RANDOM +): (axi_buses, cpu) = prepare_test_environment(dut) for test_case in range(test_cases): await test_decoder(dut, test_case, block_type, axi_buses, cpu) @@ -277,13 +297,13 @@ async def zstd_reset_test(dut): @cocotb.test(timeout_time=500, timeout_unit="ms") async def zstd_raw_frames_test(dut): test_cases = 5 - block_type = BlockType.RAW + block_type = data_generator.BlockType.RAW await testing_routine(dut, test_cases, block_type) @cocotb.test(timeout_time=500, timeout_unit="ms") async def zstd_rle_frames_test(dut): test_cases = 5 - block_type = BlockType.RLE + block_type = data_generator.BlockType.RLE await testing_routine(dut, test_cases, block_type) #@cocotb.test(timeout_time=1000, timeout_unit="ms") @@ -314,5 +334,5 @@ async def zstd_rle_frames_test(dut): "xls/modules/zstd/external/arbiter.v", "xls/modules/zstd/external/priority_encoder.v", ] - test_module=[Path(__file__).stem] + test_module=[pathlib.Path(__file__).stem] run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/zstd_frame_dslx.py b/xls/modules/zstd/zstd_frame_dslx.py index 65c5573677..c5ad2e177b 100644 --- a/xls/modules/zstd/zstd_frame_dslx.py +++ b/xls/modules/zstd/zstd_frame_dslx.py @@ -12,28 +12,47 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""ZSTD test frame generator for DSLX tests. + +This module interacts with the data_generator module and underlying +Decodecorpus in order to generate inputs and expected outputs for the ZSTD +Decoder tests in DSLX. + +It generates the ZSTD frame and then decodes it with the reference ZSTD +library. Both the encoded frame and decoded data are written to a DSLX file by +converting raw bytes of the frame and decoded data into DSLX structures. + +Resulting file can be included in the ZSTD Decoder DSLX test and used as the +inputs and expected output for the testbench. +""" import argparse import math import random import tempfile -from pathlib import Path +import pathlib -from xls.modules.zstd.cocotb.data_generator import ( - BlockType, - DecompressFrame, - GenerateFrame, -) +from xls.modules.zstd.cocotb import data_generator def GenerateTestData(seed, btype): with tempfile.NamedTemporaryFile() as tmp: - GenerateFrame(seed, btype, tmp.name) + data_generator.GenerateFrame(seed, btype, tmp.name) tmp.seek(0) return tmp.read() def Bytes2DSLX(frames, bytes_per_word, array_name): + """Converts a list of byte frames to a DSLX constant array declaration. + + Args: + frames (List[bytes]): List of byte sequences representing frames. + bytes_per_word (int): Number of bytes per word in the output format. + array_name (str): Name of the resulting DSLX constant array. + + Returns: + str: A string containing the DSLX constant array declaration. + """ frames_hex = [] maxlen = max(len(frame) for frame in frames) maxlen_size = math.ceil(maxlen / bytes_per_word) @@ -70,49 +89,13 @@ def Bytes2DSLX(frames, bytes_per_word, array_name): def GenerateDataStruct(): return ( - f"pub struct DataArray{{\n" - f" data: uN[BITS_PER_WORD][LENGTH],\n" - f" length: u32,\n" - f" array_length: u32\n" - f"}}\n" + "pub struct DataArray{\n" + " data: uN[BITS_PER_WORD][LENGTH],\n" + " length: u32,\n" + " array_length: u32\n" + "}\n" ) -def main2(): - parser = argparse.ArgumentParser() - parser.add_argument( - "input", - help="Filename of the decodecorpus input", - type=Path, - ) - parser.add_argument( - "output", - help="Filename of the DSLX output file", - type=Path, - ) - parser.add_argument( - "--bytes-per-word", - help="Width of a word in memory, in bytes", - type=int, - default=8, - ) - - args = parser.parse_args() - - with open(args.input, "rb") as fd: - byte_frames = [fd.read()] - - with open(args.output, "w") as dslx_output: - dslx_output.write(GenerateDataStruct()) - - dslx_frames = Bytes2DSLX(byte_frames, args.bytes_per_word, "FRAMES") - dslx_output.write(dslx_frames) - - byte_frames_decompressed = list(map(DecompressFrame, byte_frames)) - dslx_frames_decompressed = Bytes2DSLX( - byte_frames_decompressed, args.bytes_per_word, "DECOMPRESSED_FRAMES" - ) - dslx_output.write(dslx_frames_decompressed) - def main(): parser = argparse.ArgumentParser() @@ -128,17 +111,17 @@ def main(): "Block types allowed in the generated testcases. If multiple block types " "are supplied, generated testcases will cycle through them" ), - type=BlockType.from_string, - choices=list(BlockType), - default=BlockType.RANDOM, + type=data_generator.BlockType.from_string, + choices=list(data_generator.BlockType), + default=data_generator.BlockType.RANDOM, nargs="+", ) parser.add_argument( "-o", "--output", help="Filename of the DSLX output file", - type=Path, - default=Path("frames_test_data.x"), + type=pathlib.Path, + default=pathlib.Path("frames_test_data.x"), ) parser.add_argument( "--bytes-per-word", @@ -148,7 +131,7 @@ def main(): ) args = parser.parse_args() - seed = random.seed(args.seed) + random.seed(args.seed) byte_frames = [ GenerateTestData(random.randrange(2**32), args.btype[i % len(args.btype)]) for i in range(args.n) @@ -159,7 +142,9 @@ def main(): dslx_frames = Bytes2DSLX(byte_frames, args.bytes_per_word, "FRAMES") dslx_output.write(dslx_frames) - byte_frames_decompressed = list(map(DecompressFrame, byte_frames)) + byte_frames_decompressed = list( + map(data_generator.DecompressFrame, byte_frames) + ) dslx_frames_decompressed = Bytes2DSLX( byte_frames_decompressed, args.bytes_per_word, "DECOMPRESSED_FRAMES" ) From 6f647db36c11e9f685ffe6fc00be0419ca19747e Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Wed, 23 Jul 2025 14:33:55 +0200 Subject: [PATCH 17/30] Extend cocotb tests of ZSTD decoder Co-authored-by: Pawel Czarnecki Co-authored-by: Krzysztof Oblonczek Co-authored-by: Wojciech Sipak Co-authored-by: Dominik Lau Co-authored-by: Szymon Gizler Signed-off-by: Robert Winkler --- xls/modules/zstd/BUILD | 193 +- xls/modules/zstd/cocotb/data_generator.py | 24 +- xls/modules/zstd/cocotb/utils.py | 14 +- xls/modules/zstd/data/comp_frame.zst | Bin 0 -> 51 bytes xls/modules/zstd/data/comp_frame_fse_comp.zst | Bin 0 -> 66 bytes .../zstd/data/comp_frame_fse_repeated.zst | Bin 0 -> 92 bytes xls/modules/zstd/data/comp_frame_huffman.zst | Bin 0 -> 93 bytes .../zstd/data/comp_frame_huffman_fse.zst | Bin 0 -> 64 bytes ...erals_predefined_sequences_seed_107958.log | 30 + ...erals_predefined_sequences_seed_107958.zst | Bin 0 -> 61 bytes ...erals_predefined_sequences_seed_204626.log | 25 + ...erals_predefined_sequences_seed_204626.zst | Bin 0 -> 64 bytes ...erals_predefined_sequences_seed_210872.log | 28 + ...erals_predefined_sequences_seed_210872.zst | Bin 0 -> 80 bytes ...erals_predefined_sequences_seed_299289.log | 39 + ...erals_predefined_sequences_seed_299289.zst | Bin 0 -> 60 bytes ...erals_predefined_sequences_seed_319146.log | 26 + ...erals_predefined_sequences_seed_319146.zst | Bin 0 -> 125 bytes ...erals_predefined_sequences_seed_331938.log | 25 + ...erals_predefined_sequences_seed_331938.zst | Bin 0 -> 93 bytes ...erals_predefined_sequences_seed_333824.log | 27 + ...erals_predefined_sequences_seed_333824.zst | Bin 0 -> 56 bytes .../data/pregenerated_compressed_minimal.zst | Bin 0 -> 22 bytes .../data/pregenerated_compressed_random_1.log | 189 ++ .../data/pregenerated_compressed_random_1.zst | Bin 0 -> 505 bytes .../data/pregenerated_compressed_random_2.log | 70 + .../data/pregenerated_compressed_random_2.zst | Bin 0 -> 120 bytes .../data/pregenerated_compressed_raw_1.log | 347 +++ .../data/pregenerated_compressed_raw_1.zst | Bin 0 -> 975 bytes .../data/pregenerated_compressed_raw_2.log | 100 + .../data/pregenerated_compressed_raw_2.zst | Bin 0 -> 193 bytes .../data/pregenerated_compressed_rle_1.log | 179 ++ .../data/pregenerated_compressed_rle_1.zst | Bin 0 -> 281 bytes .../data/pregenerated_compressed_rle_2.log | 103 + .../data/pregenerated_compressed_rle_2.zst | Bin 0 -> 61 bytes .../zstd/data/pregenerated_uncompressed.zst | Bin 0 -> 18 bytes ...erals_compressed_sequences_seed_903062.log | 23 + ...erals_compressed_sequences_seed_903062.zst | Bin 0 -> 37 bytes ...erals_predefined_sequences_seed_422473.log | 25 + ...erals_predefined_sequences_seed_422473.zst | Bin 0 -> 40 bytes ...erals_predefined_sequences_seed_436965.log | 23 + ...erals_predefined_sequences_seed_436965.zst | Bin 0 -> 36 bytes ...erals_predefined_sequences_seed_462302.log | 21 + ...erals_predefined_sequences_seed_462302.zst | Bin 0 -> 31 bytes ...raw_literals_rle_sequences_seed_700216.log | 20 + ...raw_literals_rle_sequences_seed_700216.zst | Bin 0 -> 46 bytes ...erals_compressed_sequences_seed_701326.log | 87 + ...erals_compressed_sequences_seed_701326.zst | Bin 0 -> 75 bytes ...erals_predefined_sequences_seed_406229.log | 37 + ...erals_predefined_sequences_seed_406229.zst | Bin 0 -> 42 bytes ...erals_predefined_sequences_seed_411034.log | 28 + ...erals_predefined_sequences_seed_411034.zst | Bin 0 -> 35 bytes ...erals_predefined_sequences_seed_413015.log | 53 + ...erals_predefined_sequences_seed_413015.zst | Bin 0 -> 64 bytes ...erals_predefined_sequences_seed_436165.log | 34 + ...erals_predefined_sequences_seed_436165.zst | Bin 0 -> 38 bytes ...erals_predefined_sequences_seed_464057.log | 21 + ...erals_predefined_sequences_seed_464057.zst | Bin 0 -> 27 bytes ...erals_predefined_sequences_seed_466803.log | 24 + ...erals_predefined_sequences_seed_466803.zst | Bin 0 -> 32 bytes .../rle_literals_rle_sequences_seed_2.log | 43 + .../rle_literals_rle_sequences_seed_2.zst | Bin 0 -> 121 bytes ...erals_predefined_sequences_seed_408158.log | 111 + ...erals_predefined_sequences_seed_408158.zst | Bin 0 -> 93 bytes ...erals_predefined_sequences_seed_499212.log | 44 + ...erals_predefined_sequences_seed_499212.zst | Bin 0 -> 60 bytes ...erals_compressed_sequences_seed_400077.log | 80 + ...erals_compressed_sequences_seed_400077.zst | Bin 0 -> 142 bytes ...d_rle_compressed_sequences_seed_400025.log | 46 + ...d_rle_compressed_sequences_seed_400025.zst | Bin 0 -> 140 bytes ...d_rle_compressed_sequences_seed_400061.log | 81 + ...d_rle_compressed_sequences_seed_400061.zst | Bin 0 -> 244 bytes ...man_literals_rle_sequences_seed_403927.log | 53 + ...man_literals_rle_sequences_seed_403927.zst | Bin 0 -> 137 bytes .../zstd/external/axi_crossbar_wrapper.v | 788 +++++- xls/modules/zstd/rtl/BUILD | 1 + xls/modules/zstd/rtl/ram_1r1w.v | 88 + xls/modules/zstd/rtl/zstd_dec_wrapper.sv | 2393 ++++++++++++++++- xls/modules/zstd/zstd_dec_cocotb_test.py | 1572 ++++++++++- xls/modules/zstd/zstd_dec_ll_fse_default.mem | 256 ++ xls/modules/zstd/zstd_dec_ml_fse_default.mem | 256 ++ xls/modules/zstd/zstd_dec_of_fse_default.mem | 256 ++ 82 files changed, 7631 insertions(+), 252 deletions(-) create mode 100644 xls/modules/zstd/data/comp_frame.zst create mode 100644 xls/modules/zstd/data/comp_frame_fse_comp.zst create mode 100644 xls/modules/zstd/data/comp_frame_fse_repeated.zst create mode 100644 xls/modules/zstd/data/comp_frame_huffman.zst create mode 100644 xls/modules/zstd/data/comp_frame_huffman_fse.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_210872.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_210872.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.zst create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.log create mode 100644 xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_minimal.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_random_1.log create mode 100644 xls/modules/zstd/data/pregenerated_compressed_random_1.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_random_2.log create mode 100644 xls/modules/zstd/data/pregenerated_compressed_random_2.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_raw_1.log create mode 100644 xls/modules/zstd/data/pregenerated_compressed_raw_1.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_raw_2.log create mode 100644 xls/modules/zstd/data/pregenerated_compressed_raw_2.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_rle_1.log create mode 100644 xls/modules/zstd/data/pregenerated_compressed_rle_1.zst create mode 100644 xls/modules/zstd/data/pregenerated_compressed_rle_2.log create mode 100644 xls/modules/zstd/data/pregenerated_compressed_rle_2.zst create mode 100644 xls/modules/zstd/data/pregenerated_uncompressed.zst create mode 100644 xls/modules/zstd/data/raw_literals_compressed_sequences_seed_903062.log create mode 100644 xls/modules/zstd/data/raw_literals_compressed_sequences_seed_903062.zst create mode 100644 xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.log create mode 100644 xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.zst create mode 100644 xls/modules/zstd/data/raw_literals_predefined_sequences_seed_436965.log create mode 100644 xls/modules/zstd/data/raw_literals_predefined_sequences_seed_436965.zst create mode 100644 xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.log create mode 100644 xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.zst create mode 100644 xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.log create mode 100644 xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.zst create mode 100644 xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.log create mode 100644 xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.zst create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.log create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.zst create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.log create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.zst create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.log create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.zst create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.log create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.zst create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_464057.log create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_464057.zst create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_466803.log create mode 100644 xls/modules/zstd/data/rle_literals_predefined_sequences_seed_466803.zst create mode 100644 xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.log create mode 100644 xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.zst create mode 100644 xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.log create mode 100644 xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.zst create mode 100644 xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_499212.log create mode 100644 xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_499212.zst create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_compressed_sequences_seed_400077.log create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_compressed_sequences_seed_400077.zst create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.log create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.zst create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.log create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.zst create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.log create mode 100644 xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.zst create mode 100644 xls/modules/zstd/rtl/ram_1r1w.v create mode 100644 xls/modules/zstd/zstd_dec_ll_fse_default.mem create mode 100644 xls/modules/zstd/zstd_dec_ml_fse_default.mem create mode 100644 xls/modules/zstd/zstd_dec_of_fse_default.mem diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index fa75755341..9dff798ed4 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -839,7 +839,7 @@ SEQUENCE_EXECUTOR_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { "delay_model": "asap7", "ram_configurations": ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "ram{}".format(num), rd_req = "sequence_executor__rd_req_m{}_s".format(num), rd_resp = "sequence_executor__rd_resp_m{}_r".format(num), @@ -1186,7 +1186,7 @@ xls_dslx_verilog( "delay_model": "asap7", # FIXME: update ram rewrite #"ram_configurations": "ram:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - # latency = 5, + # latency = 1, # rd_req = "fse_proba_freq_dec__rd_req_s", # rd_resp = "fse_proba_freq_dec__rd_resp_r", # wr_req = "fse_proba_freq_dec__wr_req_s", @@ -1212,7 +1212,7 @@ xls_benchmark_ir( "reset": "rst", # FIXME: update ram rewrite #"ram_configurations": "ram:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - # latency = 5, + # latency = 1, # rd_req = "fse_proba_freq_dec__rd_req_s", # rd_resp = "fse_proba_freq_dec__rd_resp_r", # wr_req = "fse_proba_freq_dec__wr_req_s", @@ -1521,14 +1521,14 @@ ZSTD_DEC_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { "module_name": "ZstdDecoder", "clock_period_ps": "0", "pipeline_stages": "16", - "flop_inputs_kind": "skid", - "flop_outputs_kind": "skid", "worst_case_throughput": "6", + # "flop_inputs_kind": "skid", + # "flop_outputs_kind": "skid", "materialize_internal_fifos": "false", # TODO: remove once this option works with loopback channels "ram_configurations": ",".join([ ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "history_buffer_ram{}".format(num), rd_req = "zstd_dec__ram_rd_req_{}_s".format(num), rd_resp = "zstd_dec__ram_rd_resp_{}_r".format(num), @@ -1538,7 +1538,7 @@ ZSTD_DEC_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { for num in range(8) ]), "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "dpd_ram", rd_req = "zstd_dec__dpd_rd_req_s", rd_resp = "zstd_dec__dpd_rd_resp_r", @@ -1546,7 +1546,7 @@ ZSTD_DEC_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { wr_resp = "zstd_dec__dpd_wr_resp_r", ), "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "fse_tmp_ram", rd_req = "zstd_dec__tmp_rd_req_s", rd_resp = "zstd_dec__tmp_rd_resp_r", @@ -1554,44 +1554,112 @@ ZSTD_DEC_CODEGEN_ARGS = COMMON_CODEGEN_ARGS | { wr_resp = "zstd_dec__tmp_wr_resp_r", ), "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "fse_tmp2_ram", rd_req = "zstd_dec__tmp2_rd_req_s", rd_resp = "zstd_dec__tmp2_rd_resp_r", wr_req = "zstd_dec__tmp2_wr_req_s", wr_resp = "zstd_dec__tmp2_wr_resp_r", ), - ",".join([ - "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, - ram_name = "fse_lookup_ram{}".format(num), - rd_req = "zstd_dec__fse_rd_req_s__{}".format(num), - rd_resp = "zstd_dec__fse_rd_resp_r__{}".format(num), - wr_req = "zstd_dec__fse_wr_req_s__{}".format(num), - wr_resp = "zstd_dec__fse_wr_resp_r__{}".format(num), - ) - for num in range(6) - ]), "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, + ram_name = "ll_def_fse_ram", + rd_req = "zstd_dec__ll_def_fse_rd_req_s", + rd_resp = "zstd_dec__ll_def_fse_rd_resp_r", + wr_req = "zstd_dec__ll_def_fse_wr_req_s", + wr_resp = "zstd_dec__ll_def_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "ll_fse_ram", + rd_req = "zstd_dec__ll_fse_rd_req_s", + rd_resp = "zstd_dec__ll_fse_rd_resp_r", + wr_req = "zstd_dec__ll_fse_wr_req_s", + wr_resp = "zstd_dec__ll_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "ml_def_fse_ram", + rd_req = "zstd_dec__ml_def_fse_rd_req_s", + rd_resp = "zstd_dec__ml_def_fse_rd_resp_r", + wr_req = "zstd_dec__ml_def_fse_wr_req_s", + wr_resp = "zstd_dec__ml_def_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "ml_fse_ram", + rd_req = "zstd_dec__ml_fse_rd_req_s", + rd_resp = "zstd_dec__ml_fse_rd_resp_r", + wr_req = "zstd_dec__ml_fse_wr_req_s", + wr_resp = "zstd_dec__ml_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "of_def_fse_ram", + rd_req = "zstd_dec__of_def_fse_rd_req_s", + rd_resp = "zstd_dec__of_def_fse_rd_resp_r", + wr_req = "zstd_dec__of_def_fse_wr_req_s", + wr_resp = "zstd_dec__of_def_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "of_fse_ram", + rd_req = "zstd_dec__of_fse_rd_req_s", + rd_resp = "zstd_dec__of_fse_rd_resp_r", + wr_req = "zstd_dec__of_fse_wr_req_s", + wr_resp = "zstd_dec__of_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, ram_name = "huffman_literals_prescan_ram", rd_req = "zstd_dec__huffman_lit_prescan_mem_rd_req_s", rd_resp = "zstd_dec__huffman_lit_prescan_mem_rd_resp_r", wr_req = "zstd_dec__huffman_lit_prescan_mem_wr_req_s", wr_resp = "zstd_dec__huffman_lit_prescan_mem_wr_resp_r", ), - # FIXME: Enable once HuffmanLiteralsDecoder has states independent of data read from RAM - #"{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - # latency = 5, - # ram_name = "huffman_literals_weights_ram", - # rd_req = "zstd_dec__huffman_lit_weights_mem_rd_req_s", - # rd_resp = "zstd_dec__huffman_lit_weights_mem_rd_resp_r", - # wr_req = "zstd_dec__huffman_lit_weights_mem_wr_req_s", - # wr_resp = "zstd_dec__huffman_lit_weights_mem_wr_resp_r", - #), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "huffman_literals_weights_dpd_ram", + rd_req = "zstd_dec__huffman_lit_weights_dpd_rd_req_s", + rd_resp = "zstd_dec__huffman_lit_weights_dpd_rd_resp_r", + wr_req = "zstd_dec__huffman_lit_weights_dpd_wr_req_s", + wr_resp = "zstd_dec__huffman_lit_weights_dpd_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "huffman_literals_weights_tmp_ram", + rd_req = "zstd_dec__huffman_lit_weights_tmp_rd_req_s", + rd_resp = "zstd_dec__huffman_lit_weights_tmp_rd_resp_r", + wr_req = "zstd_dec__huffman_lit_weights_tmp_wr_req_s", + wr_resp = "zstd_dec__huffman_lit_weights_tmp_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "huffman_literals_weights_tmp2_ram", + rd_req = "zstd_dec__huffman_lit_weights_tmp2_rd_req_s", + rd_resp = "zstd_dec__huffman_lit_weights_tmp2_rd_resp_r", + wr_req = "zstd_dec__huffman_lit_weights_tmp2_wr_req_s", + wr_resp = "zstd_dec__huffman_lit_weights_tmp2_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "huffman_literals_weights_fse_ram", + rd_req = "zstd_dec__huffman_lit_weights_fse_rd_req_s", + rd_resp = "zstd_dec__huffman_lit_weights_fse_rd_resp_r", + wr_req = "zstd_dec__huffman_lit_weights_fse_wr_req_s", + wr_resp = "zstd_dec__huffman_lit_weights_fse_wr_resp_r", + ), + "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( + latency = 1, + ram_name = "huffman_literals_weights_mem_ram", + rd_req = "zstd_dec__huffman_lit_weights_mem_rd_req_s", + rd_resp = "zstd_dec__huffman_lit_weights_mem_rd_resp_r", + wr_req = "zstd_dec__huffman_lit_weights_mem_wr_req_s", + wr_resp = "zstd_dec__huffman_lit_weights_mem_wr_resp_r", + ), ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "literals_buffer_ram{}".format(num), rd_req = "zstd_dec__litbuf_rd_req_s__{}".format(num), rd_resp = "zstd_dec__litbuf_rd_resp_r__{}".format(num), @@ -1708,11 +1776,60 @@ benchmark_synth( # target_die_utilization_percentage = "1", #) +filegroup( + name = "zstd_dec_xx_fse_default", + srcs = [ + "zstd_dec_ll_fse_default.mem", + "zstd_dec_ml_fse_default.mem", + "zstd_dec_of_fse_default.mem", + ], +) + py_test( name = "zstd_dec_cocotb_test", srcs = ["zstd_dec_cocotb_test.py"], data = [ + "data/comp_frame.zst", + "data/comp_frame_fse_comp.zst", + "data/comp_frame_fse_repeated.zst", + "data/comp_frame_huffman.zst", + "data/comp_frame_huffman_fse.zst", + "data/fse_huffman_literals_predefined_sequences_seed_107958.zst", + "data/fse_huffman_literals_predefined_sequences_seed_204626.zst", + "data/fse_huffman_literals_predefined_sequences_seed_210872.zst", + "data/fse_huffman_literals_predefined_sequences_seed_299289.zst", + "data/fse_huffman_literals_predefined_sequences_seed_319146.zst", + "data/fse_huffman_literals_predefined_sequences_seed_331938.zst", + "data/fse_huffman_literals_predefined_sequences_seed_333824.zst", + "data/pregenerated_compressed_minimal.zst", + "data/pregenerated_compressed_random_1.zst", + "data/pregenerated_compressed_random_2.zst", + "data/pregenerated_compressed_raw_1.zst", + "data/pregenerated_compressed_raw_2.zst", + "data/pregenerated_compressed_rle_1.zst", + "data/pregenerated_compressed_rle_2.zst", + "data/pregenerated_uncompressed.zst", + "data/raw_literals_compressed_sequences_seed_903062.zst", + "data/raw_literals_predefined_sequences_seed_422473.zst", + "data/raw_literals_predefined_sequences_seed_436965.zst", + "data/raw_literals_predefined_sequences_seed_462302.zst", + "data/raw_literals_rle_sequences_seed_700216.zst", + "data/rle_literals_compressed_sequences_seed_701326.zst", + "data/rle_literals_predefined_sequences_seed_406229.zst", + "data/rle_literals_predefined_sequences_seed_411034.zst", + "data/rle_literals_predefined_sequences_seed_413015.zst", + "data/rle_literals_predefined_sequences_seed_436165.zst", + "data/rle_literals_predefined_sequences_seed_464057.zst", + "data/rle_literals_predefined_sequences_seed_466803.zst", + "data/rle_literals_rle_sequences_seed_2.zst", + "data/rle_raw_literals_predefined_sequences_seed_408158.zst", + "data/rle_raw_literals_predefined_sequences_seed_499212.zst", + "data/treeless_huffman_literals_compressed_sequences_seed_400077.zst", + "data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.zst", + "data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.zst", + "data/treeless_huffman_literals_rle_sequences_seed_403927.zst", ":zstd_dec.v", + "//xls/modules/zstd:zstd_dec_xx_fse_default", "//xls/modules/zstd/external:arbiter.v", "//xls/modules/zstd/external:axi_crossbar.v", "//xls/modules/zstd/external:axi_crossbar_addr.v", @@ -1722,12 +1839,16 @@ py_test( "//xls/modules/zstd/external:axi_register_rd.v", "//xls/modules/zstd/external:axi_register_wr.v", "//xls/modules/zstd/external:priority_encoder.v", + "//xls/modules/zstd/rtl:ram_1r1w.v", "//xls/modules/zstd/rtl:xls_fifo_wrapper.sv", "//xls/modules/zstd/rtl:zstd_dec_wrapper.sv", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], - env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, + env = { + "BUILD_WORKING_DIRECTORY": "sim_build", + "PYTHONUNBUFFERED": "1", + }, imports = ["."], tags = ["manual"], visibility = ["//xls:xls_users"], @@ -2080,7 +2201,7 @@ RAM_DEMUX_CODEGEN_ARGS = { "worst_case_throughput": "6", "ram_configurations": ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "ram{}".format(num), rd_req = "ram_demux__rd_req{}_s".format(num), rd_resp = "ram_demux__rd_resp{}_r".format(num), @@ -2371,7 +2492,7 @@ xls_dslx_verilog( "delay_model": "asap7", "ram_configurations": ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "ram{}".format(num), rd_req = "ram_demux3__rd_req{}_s".format(num), rd_resp = "ram_demux3__rd_resp{}_r".format(num), @@ -2782,7 +2903,7 @@ xls_dslx_verilog( "delay_model": "asap7", "ram_configurations": ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "ram{}".format(num), rd_req = "literals_buffer__rd_req_m{}_s".format(num), rd_resp = "literals_buffer__rd_resp_m{}_r".format(num), @@ -2949,7 +3070,7 @@ LITERALS_DECODER_CODEGEN_ARGS = { "delay_model": "asap7", "ram_configurations": ",".join([ "{ram_name}:1R1W:{rd_req}:{rd_resp}:{wr_req}:{wr_resp}:{latency}".format( - latency = 5, + latency = 1, ram_name = "ram{}".format(num), rd_req = "literals_decoder__rd_req_m{}_s".format(num), rd_resp = "literals_decoder__rd_resp_m{}_r".format(num), diff --git a/xls/modules/zstd/cocotb/data_generator.py b/xls/modules/zstd/cocotb/data_generator.py index 46a74acbfc..3c9233f6d6 100644 --- a/xls/modules/zstd/cocotb/data_generator.py +++ b/xls/modules/zstd/cocotb/data_generator.py @@ -39,6 +39,24 @@ def from_string(s): except KeyError as e: raise ValueError(str(e)) from e +class LiteralType(enum.Enum): + """Enum encoding of ZSTD literal types.""" + + RAW = 0 + RLE = 1 + COMPRESSED = 2 + RANDOM = 3 + + def __str__(self): + return self.name + + @staticmethod + def from_string(s): + try: + return BlockType[s] + except KeyError as e: + raise ValueError(str(e)) from e + def CallDecodecorpus(args): decodecorpus = pathlib.Path( runfiles.get_path("decodecorpus", repository = "zstd") @@ -52,11 +70,15 @@ def DecompressFrame(data): dctx = zstandard.ZstdDecompressor() return dctx.decompress(data) -def GenerateFrame(seed, btype, output_path): +def GenerateFrame(seed, btype, output_path, ltype=LiteralType.RANDOM): args = [] args.append("-s" + str(seed)) if (btype != BlockType.RANDOM): args.append("--block-type=" + str(btype.value)) + + if (ltype != LiteralType.RANDOM): + args.append("--literal-type=" + str(ltype.value)) + args.append("--content-size") # Test payloads up to 16KB args.append("--max-content-size-log=14") diff --git a/xls/modules/zstd/cocotb/utils.py b/xls/modules/zstd/cocotb/utils.py index 7fda01b0b9..01688f96a3 100644 --- a/xls/modules/zstd/cocotb/utils.py +++ b/xls/modules/zstd/cocotb/utils.py @@ -50,12 +50,14 @@ def run_test(toplevel, test_module, verilog_sources): waves=True, ) - results_xml = runner.test( - hdl_toplevel=toplevel, - test_module=test_module, - waves=True, - ) - check_results_file(results_xml) + try: + results_xml = runner.test( + hdl_toplevel=toplevel, + test_module=test_module, + waves=True, + ) + finally: + check_results_file(results_xml) @cocotb.coroutine async def reset(clk, rst, cycles=1): diff --git a/xls/modules/zstd/data/comp_frame.zst b/xls/modules/zstd/data/comp_frame.zst new file mode 100644 index 0000000000000000000000000000000000000000..800a7bdca91d4fbddaf33411a2402d7ef59ec7df GIT binary patch literal 51 zcmV-30L=d=wJ-gIM^FF&02KiMaFx%*ldOrkP<`PD=BAYh0Iv5Ma6JW`-kC J;IIYbaD*4377qXb literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/comp_frame_fse_comp.zst b/xls/modules/zstd/data/comp_frame_fse_comp.zst new file mode 100644 index 0000000000000000000000000000000000000000..f9cf4a5d1fee7bfb26a6a87f5549c28e44cf8b21 GIT binary patch literal 66 zcmV-I0KNYxwJ-gIP*eZ_0F40v&^AI31@t#{HJBY6dDqsiwUUi=l>sT&j#E(ss1b(y Y0TFOn(Fbvb|Idp3V+xM51cp>m#Z)F6f&c&j literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/comp_frame_fse_repeated.zst b/xls/modules/zstd/data/comp_frame_fse_repeated.zst new file mode 100644 index 0000000000000000000000000000000000000000..8fed4b3fbe63c83cc93ddfe47fbfd9d14d5d3797 GIT binary patch literal 92 zcmdPcs{gk|#g2i2p@o5=@)}bHqaa(oVB7!yb$5eUTo@P(QyELx7`L&=Ffb@?W&o0m d&%q=wnA{5{t-xeGn9OF71**wp*f!I4CIA*T6FC3? literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/comp_frame_huffman.zst b/xls/modules/zstd/data/comp_frame_huffman.zst new file mode 100644 index 0000000000000000000000000000000000000000..7f21a9f870ae0fefcb79022ea0c563252319b462 GIT binary patch literal 93 zcmdPcs{gmerGSBfA(e^2ig^t~pCAMXurq+5Pdi(f6|0nRi)qZ39FgslOBchq5d8nX-tPbV^Y-um?_FR1KlV2x TGsA`n4`mg3{5V!L*EIkD+e#Sp literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.log b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.log new file mode 100644 index 0000000000..74008be9c2 --- /dev/null +++ b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.log @@ -0,0 +1,30 @@ +seed: 107958 +frame seed: 107958 + frame content size: 100 + frame window size: 1536 + content size flag: 1 + single segment flag: 0 + block: + block content size: 100 + last block: yes + compressed block: + compressed literals + distribution weight: 81% + huffman log: 10 + regenerated size: 45 + compressed size: 22 + literals size: 45 + total match lengths: 55 + LL: 13 OF: 9 ML: 4 srcPos: 17 seqNb: 0 + LL: 12 OF: 6 ML: 9 srcPos: 38 seqNb: 1 + LL: 3 OF: 36 ML: 25 srcPos: 66 seqNb: 2 + LL: 0 OF: 42 ML: 5 srcPos: 71 seqNb: 3 + LL: 14 OF: 2 ML: 5 srcPos: 90 seqNb: 4 + LL: 0 OF: 27 ML: 3 srcPos: 93 seqNb: 5 + LL: 1 OF: 67 ML: 4 srcPos: 98 seqNb: 6 + excess literals: 2 srcPos: 100 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 7 + block type: compressed + block size field: 44 + checksum: 61c6e5a0 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.zst b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_107958.zst new file mode 100644 index 0000000000000000000000000000000000000000..b44e0191ea5b9139965130057d3b415d874e51b2 GIT binary patch literal 61 zcmV-D0K)$$wJ-gI1Y`gJ0A&FH(t-sJ&}BFPumXTV3h1JO#smBR-+%YrsRsZ?2*f7< TxznavaMT(pl`tq@pykG4*5etX literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.log b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.log new file mode 100644 index 0000000000..6a11616659 --- /dev/null +++ b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.log @@ -0,0 +1,25 @@ +seed: 204626 +frame seed: 204626 + frame content size: 89 + frame window size: 1152 + content size flag: 1 + single segment flag: 0 + block: + block content size: 89 + last block: yes + compressed block: + compressed literals + distribution weight: 64% + huffman log: 9 + regenerated size: 66 + compressed size: 36 + literals size: 66 + total match lengths: 23 + LL: 42 OF: 16 ML: 9 srcPos: 51 seqNb: 0 + LL: 24 OF: 6 ML: 14 srcPos: 89 seqNb: 1 + excess literals: 0 srcPos: 89 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 2 + block type: compressed + block size field: 47 + checksum: 9834e3da diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.zst b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_204626.zst new file mode 100644 index 0000000000000000000000000000000000000000..cc5812eb6ae7bf59dca1efd3eb6e4388601a463f GIT binary patch literal 64 zcmV-G0KfkzwJ-gI0a*Y50DS=fA_NH)pe2QL|0Dm?|Fiz?`Z9`A?>> jFa1!@^wT_$t=97~6Dva(rwE^po`i(~3m>;o{=|F$trHuh literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.log b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.log new file mode 100644 index 0000000000..f2f01bd94a --- /dev/null +++ b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.log @@ -0,0 +1,39 @@ +seed: 299289 +frame seed: 299289 + frame content size: 68 + frame window size: 294912 + content size flag: 1 + single segment flag: 0 + block: + block content size: 68 + last block: yes + compressed block: + compressed literals + distribution weight: 24% + huffman log: 11 + regenerated size: 60 + compressed size: 74 + trying again + distribution weight: 44% + huffman log: 9 + regenerated size: 41 + compressed size: 45 + trying again + distribution weight: 86% + huffman log: 11 + regenerated size: 46 + compressed size: 26 + literals size: 46 + total match lengths: 22 + LL: 7 OF: 6 ML: 5 srcPos: 12 seqNb: 0 + LL: 5 OF: 8 ML: 4 srcPos: 21 seqNb: 1 + LL: 18 OF: 1 ML: 6 srcPos: 45 seqNb: 2 + repeat offset: 2 + LL: 0 OF: 16 ML: 4 srcPos: 49 seqNb: 3 + LL: 16 OF: 29 ML: 3 srcPos: 68 seqNb: 4 + excess literals: 0 srcPos: 68 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 5 + block type: compressed + block size field: 43 + checksum: 28ab4e28 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.zst b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_299289.zst new file mode 100644 index 0000000000000000000000000000000000000000..c19b07faf2a3950c60c7f74bab83753da37a2206 GIT binary patch literal 60 zcmdPcs{gme(S?D5A(oNhSrZ%ggG`=P{>(uB(HtfQ5PWa{b^rfc-}zY?8k*)xHk2Ro N+7pw?t>L#?0{~9@6vO}k literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.log b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.log new file mode 100644 index 0000000000..dc4eaae5ff --- /dev/null +++ b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.log @@ -0,0 +1,26 @@ +seed: 319146 +frame seed: 319146 + frame content size: 114 + frame window size: 720896 + content size flag: 1 + single segment flag: 0 + block: + block content size: 114 + last block: yes + compressed block: + compressed literals + distribution weight: 23% + huffman log: 10 + regenerated size: 105 + compressed size: 91 + literals size: 105 + total match lengths: 9 + LL: 90 OF: 16 ML: 4 srcPos: 94 seqNb: 0 + LL: 15 OF: 1 ML: 5 srcPos: 114 seqNb: 1 + repeat offset: 1 + excess literals: 0 srcPos: 114 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 2 + block type: compressed + block size field: 104 + checksum: 9a966cac diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.zst b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_319146.zst new file mode 100644 index 0000000000000000000000000000000000000000..f5b2d6c1575257a12d957e80f41279d3f037b442 GIT binary patch literal 125 zcmdPcs{i+hcM$^wxH2=$V>=+mpx&VBd5N*M&%4!Abb`UsL)L4(4p`eh4N44Jn&7&s zfhCmbUgp(9tGRd>xEXjDo<#KNuVKH|(Q`2@YkIQV?bo+vCVyHjDlP19rf)H+gx5Ti cbxGO3=*gQaBbvFH7}ka4Hc7Is$(c3_0QPJzW&i*H literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.log b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.log new file mode 100644 index 0000000000..557c6176f1 --- /dev/null +++ b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.log @@ -0,0 +1,25 @@ +seed: 331938 +frame seed: 331938 + frame content size: 104 + frame window size: 36864 + content size flag: 1 + single segment flag: 0 + block: + block content size: 104 + last block: yes + compressed block: + compressed literals + distribution weight: 37% + huffman log: 9 + regenerated size: 67 + compressed size: 60 + literals size: 67 + total match lengths: 37 + LL: 31 OF: 31 ML: 23 srcPos: 54 seqNb: 0 + LL: 19 OF: 13 ML: 14 srcPos: 87 seqNb: 1 + excess literals: 17 srcPos: 104 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 2 + block type: compressed + block size field: 72 + checksum: d76a8c9e diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.zst b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_331938.zst new file mode 100644 index 0000000000000000000000000000000000000000..943fafbf00fffabb1fa2d2784f50c5cfb70ceba8 GIT binary patch literal 93 zcmdPcs{i+hW(ETUxH2(Vv3y{VnV{-v^|}1Zgt>J$_OH3BU;6cF_^+w*D~+EPeG_J5 vU}s=s(7L))x}52;xSZD~N$*wq>iHq8tCng!n#|9{ka#LFaJ9|6o~-KtQv4(n literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.log b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.log new file mode 100644 index 0000000000..025dfe3f63 --- /dev/null +++ b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.log @@ -0,0 +1,27 @@ +seed: 333824 +frame seed: 333824 + frame content size: 109 + frame window size: 109 + content size flag: 1 + single segment flag: 1 + block: + block content size: 109 + last block: yes + compressed block: + compressed literals + distribution weight: 74% + huffman log: 9 + regenerated size: 86 + compressed size: 30 + literals size: 86 + total match lengths: 23 + LL: 10 OF: 5 ML: 3 srcPos: 13 seqNb: 0 + LL: 45 OF: 40 ML: 10 srcPos: 68 seqNb: 1 + LL: 21 OF: 5 ML: 10 srcPos: 99 seqNb: 2 + repeat offset: 1 + excess literals: 10 srcPos: 109 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 3 + block type: compressed + block size field: 43 + checksum: 5905f5bb diff --git a/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.zst b/xls/modules/zstd/data/fse_huffman_literals_predefined_sequences_seed_333824.zst new file mode 100644 index 0000000000000000000000000000000000000000..51b18d62b87ad7cfbad0b4f5e96e4cccda62bc75 GIT binary patch literal 56 zcmdPcs{dCdHZg`6ou9S z5JU*~5J;8PI8mhQEFGL?0Nh8g z4m2p9q(C15-jpEd0N`!#j#oYixCUef0Hc8$0VoX2|kOt6L zkPomvu%rNiO5lnD3<$uwhTkK=IHVu!04+dF0N@Bn&j166X8?!uzbLO0x}3Ppn%bWE^@Ud$Q%Yiz?mQboC^>)^sTYxgG_2nAe#AqD^v0Qw~? vEl4>)P9^5f~RykOuNWH4MB5uq}Ww-~kj7zL$y8fFai2 literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/pregenerated_compressed_random_2.log b/xls/modules/zstd/data/pregenerated_compressed_random_2.log new file mode 100644 index 0000000000..e120ce7b47 --- /dev/null +++ b/xls/modules/zstd/data/pregenerated_compressed_random_2.log @@ -0,0 +1,70 @@ +seed: 2 +frame seed: 2 + frame content size: 152 + frame window size: 114688 + content size flag: 1 + single segment flag: 0 + block: + block content size: 91 + last block: no + compressed block: + compressed literals + distribution weight: 33% + huffman log: 10 + regenerated size: 44 + compressed size: 49 + trying again + distribution weight: 64% + huffman log: 8 + regenerated size: 35 + compressed size: 30 + literals size: 35 + total match lengths: 56 + LL: 14 OF: 12 ML: 6 srcPos: 20 seqNb: 0 + LL: 1 OF: 9 ML: 9 srcPos: 30 seqNb: 1 + LL: 5 OF: 12 ML: 10 srcPos: 45 seqNb: 2 + LL: 0 OF: 39 ML: 3 srcPos: 48 seqNb: 3 + LL: 5 OF: 3 ML: 13 srcPos: 66 seqNb: 4 + LL: 10 OF: 24 ML: 15 srcPos: 91 seqNb: 5 + excess literals: 0 srcPos: 91 + LL type: 2 OF type: 2 ML type: 2 + number of sequences: 6 + block type: compressed + block size field: 61 + block: + block content size: 53 + last block: no + compressed block: + rle literals: 0xf8 + literals size: 19 + total match lengths: 34 + LL: 2 OF: 56 ML: 3 srcPos: 96 seqNb: 0 + LL: 1 OF: 56 ML: 3 srcPos: 100 seqNb: 1 + repeat offset: 0 + LL: 0 OF: 40 ML: 4 srcPos: 104 seqNb: 2 + LL: 0 OF: 48 ML: 4 srcPos: 108 seqNb: 3 + LL: 6 OF: 53 ML: 3 srcPos: 117 seqNb: 4 + LL: 5 OF: 81 ML: 3 srcPos: 125 seqNb: 5 + LL: 2 OF: 111 ML: 4 srcPos: 131 seqNb: 6 + LL: 3 OF: 79 ML: 3 srcPos: 137 seqNb: 7 + LL: 0 OF: 78 ML: 3 srcPos: 140 seqNb: 8 + LL: 0 OF: 87 ML: 4 srcPos: 144 seqNb: 9 + excess literals: 0 srcPos: 144 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 10 + block type: compressed + block size field: 29 + block: + block content size: 8 + last block: yes + compressed block: + raw literals + literals size: 0 + total match lengths: 8 + LL: 0 OF: 58 ML: 8 srcPos: 152 seqNb: 0 + excess literals: 0 srcPos: 152 + LL type: 3 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 7 + checksum: e7ab4be9 diff --git a/xls/modules/zstd/data/pregenerated_compressed_random_2.zst b/xls/modules/zstd/data/pregenerated_compressed_random_2.zst new file mode 100644 index 0000000000000000000000000000000000000000..014359109f9ab7dcc6a82d125f26aad14fcef42c GIT binary patch literal 120 zcmV-;0Eho5wJ-gIHkbea0PFz(GJ*#cpe0EMXu$vfze!Z7s;VGo5C8zf2W|GT<=Toz z9tNmjOxQ9O4-hid4uB#PnI#Jc3&^YR3!WYh3G4s>nfM9-S_BXU0HlB+M}VmSXsn>7 a3Ro%t0Nf2IEIj}K00Gnm1sw?KORMKncPS_U literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/pregenerated_compressed_raw_1.log b/xls/modules/zstd/data/pregenerated_compressed_raw_1.log new file mode 100644 index 0000000000..15e8ef895b --- /dev/null +++ b/xls/modules/zstd/data/pregenerated_compressed_raw_1.log @@ -0,0 +1,347 @@ +seed: 1 +frame seed: 1 + frame content size: 1019 + frame window size: 294912 + content size flag: 1 + single segment flag: 0 + block: + block content size: 181 + last block: no + compressed block: + raw literals + literals size: 139 + total match lengths: 42 + LL: 37 OF: 31 ML: 13 srcPos: 50 seqNb: 0 + LL: 25 OF: 16 ML: 29 srcPos: 104 seqNb: 1 + excess literals: 77 srcPos: 181 + LL type: 2 OF type: 2 ML type: 2 + number of sequences: 2 + block type: compressed + block size field: 168 + block: + block content size: 0 + last block: no + compressed block: + raw literals + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 181 + number of sequences: 0 + block type: compressed + block size field: 2 + block: + block content size: 63 + last block: no + compressed block: + raw literals + literals size: 7 + total match lengths: 56 + LL: 0 OF: 70 ML: 3 srcPos: 184 seqNb: 0 + LL: 0 OF: 56 ML: 3 srcPos: 187 seqNb: 1 + LL: 0 OF: 55 ML: 3 srcPos: 190 seqNb: 2 + repeat offset: 2 + LL: 0 OF: 23 ML: 3 srcPos: 193 seqNb: 3 + LL: 0 OF: 4 ML: 3 srcPos: 196 seqNb: 4 + LL: 0 OF: 136 ML: 3 srcPos: 199 seqNb: 5 + LL: 0 OF: 23 ML: 3 srcPos: 202 seqNb: 6 + LL: 0 OF: 28 ML: 3 srcPos: 205 seqNb: 7 + LL: 0 OF: 2 ML: 3 srcPos: 208 seqNb: 8 + LL: 1 OF: 5 ML: 3 srcPos: 212 seqNb: 9 + LL: 0 OF: 4 ML: 3 srcPos: 215 seqNb: 10 + repeat offset: 2 + LL: 0 OF: 2 ML: 3 srcPos: 218 seqNb: 11 + repeat offset: 2 + LL: 0 OF: 56 ML: 3 srcPos: 221 seqNb: 12 + LL: 2 OF: 209 ML: 3 srcPos: 226 seqNb: 13 + LL: 0 OF: 24 ML: 4 srcPos: 230 seqNb: 14 + LL: 0 OF: 14 ML: 3 srcPos: 233 seqNb: 15 + LL: 0 OF: 112 ML: 4 srcPos: 237 seqNb: 16 + LL: 0 OF: 233 ML: 3 srcPos: 240 seqNb: 17 + excess literals: 4 srcPos: 244 + LL type: 2 OF type: 2 ML type: 2 + number of sequences: 18 + block type: compressed + block size field: 39 + block: + block content size: 59 + last block: no + compressed block: + raw literals + literals size: 19 + total match lengths: 40 + LL: 2 OF: 90 ML: 6 srcPos: 252 seqNb: 0 + LL: 2 OF: 153 ML: 5 srcPos: 259 seqNb: 1 + LL: 10 OF: 76 ML: 10 srcPos: 279 seqNb: 2 + LL: 1 OF: 226 ML: 5 srcPos: 285 seqNb: 3 + LL: 2 OF: 5 ML: 4 srcPos: 291 seqNb: 4 + LL: 2 OF: 33 ML: 7 srcPos: 300 seqNb: 5 + LL: 0 OF: 262 ML: 3 srcPos: 303 seqNb: 6 + excess literals: 0 srcPos: 303 + LL type: 2 OF type: 2 ML type: 0 + number of sequences: 7 + block type: compressed + block size field: 45 + block: + block content size: 614 + last block: no + compressed block: + raw literals + literals size: 159 + total match lengths: 455 + LL: 2 OF: 128 ML: 3 srcPos: 308 seqNb: 0 + LL: 3 OF: 96 ML: 3 srcPos: 314 seqNb: 1 + LL: 0 OF: 123 ML: 3 srcPos: 317 seqNb: 2 + LL: 0 OF: 225 ML: 3 srcPos: 320 seqNb: 3 + LL: 1 OF: 172 ML: 3 srcPos: 324 seqNb: 4 + LL: 2 OF: 56 ML: 3 srcPos: 329 seqNb: 5 + LL: 2 OF: 13 ML: 3 srcPos: 334 seqNb: 6 + LL: 1 OF: 327 ML: 3 srcPos: 338 seqNb: 7 + LL: 0 OF: 264 ML: 3 srcPos: 341 seqNb: 8 + LL: 0 OF: 13 ML: 3 srcPos: 344 seqNb: 9 + repeat offset: 2 + LL: 0 OF: 340 ML: 3 srcPos: 347 seqNb: 10 + LL: 0 OF: 95 ML: 3 srcPos: 350 seqNb: 11 + LL: 0 OF: 221 ML: 3 srcPos: 353 seqNb: 12 + LL: 0 OF: 95 ML: 3 srcPos: 356 seqNb: 13 + repeat offset: 1 + LL: 0 OF: 94 ML: 3 srcPos: 359 seqNb: 14 + repeat offset: 2 + LL: 0 OF: 95 ML: 3 srcPos: 362 seqNb: 15 + repeat offset: 1 + LL: 0 OF: 294 ML: 3 srcPos: 365 seqNb: 16 + LL: 0 OF: 250 ML: 3 srcPos: 368 seqNb: 17 + LL: 3 OF: 310 ML: 3 srcPos: 374 seqNb: 18 + LL: 0 OF: 59 ML: 3 srcPos: 377 seqNb: 19 + LL: 0 OF: 17 ML: 3 srcPos: 380 seqNb: 20 + LL: 1 OF: 59 ML: 3 srcPos: 384 seqNb: 21 + repeat offset: 1 + LL: 0 OF: 372 ML: 3 srcPos: 387 seqNb: 22 + LL: 1 OF: 203 ML: 3 srcPos: 391 seqNb: 23 + LL: 1 OF: 251 ML: 3 srcPos: 395 seqNb: 24 + LL: 0 OF: 203 ML: 3 srcPos: 398 seqNb: 25 + repeat offset: 1 + LL: 1 OF: 363 ML: 3 srcPos: 402 seqNb: 26 + LL: 0 OF: 321 ML: 3 srcPos: 405 seqNb: 27 + LL: 1 OF: 395 ML: 3 srcPos: 409 seqNb: 28 + LL: 1 OF: 381 ML: 3 srcPos: 413 seqNb: 29 + LL: 3 OF: 99 ML: 3 srcPos: 419 seqNb: 30 + LL: 1 OF: 116 ML: 3 srcPos: 423 seqNb: 31 + LL: 0 OF: 293 ML: 3 srcPos: 426 seqNb: 32 + LL: 0 OF: 292 ML: 3 srcPos: 429 seqNb: 33 + repeat offset: 2 + LL: 1 OF: 127 ML: 3 srcPos: 433 seqNb: 34 + LL: 0 OF: 219 ML: 3 srcPos: 436 seqNb: 35 + LL: 0 OF: 236 ML: 3 srcPos: 439 seqNb: 36 + LL: 1 OF: 353 ML: 3 srcPos: 443 seqNb: 37 + LL: 1 OF: 46 ML: 3 srcPos: 447 seqNb: 38 + LL: 3 OF: 404 ML: 3 srcPos: 453 seqNb: 39 + LL: 0 OF: 267 ML: 3 srcPos: 456 seqNb: 40 + LL: 0 OF: 421 ML: 3 srcPos: 459 seqNb: 41 + LL: 1 OF: 201 ML: 3 srcPos: 463 seqNb: 42 + LL: 1 OF: 12 ML: 3 srcPos: 467 seqNb: 43 + LL: 0 OF: 438 ML: 3 srcPos: 470 seqNb: 44 + LL: 1 OF: 136 ML: 3 srcPos: 474 seqNb: 45 + LL: 2 OF: 126 ML: 3 srcPos: 479 seqNb: 46 + LL: 0 OF: 400 ML: 3 srcPos: 482 seqNb: 47 + LL: 0 OF: 130 ML: 3 srcPos: 485 seqNb: 48 + LL: 2 OF: 206 ML: 3 srcPos: 490 seqNb: 49 + LL: 0 OF: 302 ML: 3 srcPos: 493 seqNb: 50 + LL: 0 OF: 206 ML: 3 srcPos: 496 seqNb: 51 + LL: 1 OF: 420 ML: 3 srcPos: 500 seqNb: 52 + LL: 1 OF: 131 ML: 3 srcPos: 504 seqNb: 53 + LL: 1 OF: 172 ML: 3 srcPos: 508 seqNb: 54 + LL: 0 OF: 131 ML: 3 srcPos: 511 seqNb: 55 + repeat offset: 1 + LL: 2 OF: 438 ML: 3 srcPos: 516 seqNb: 56 + LL: 0 OF: 453 ML: 3 srcPos: 519 seqNb: 57 + LL: 0 OF: 248 ML: 3 srcPos: 522 seqNb: 58 + LL: 0 OF: 438 ML: 3 srcPos: 525 seqNb: 59 + repeat offset: 2 + LL: 1 OF: 326 ML: 3 srcPos: 529 seqNb: 60 + LL: 0 OF: 248 ML: 3 srcPos: 532 seqNb: 61 + repeat offset: 2 + LL: 1 OF: 46 ML: 3 srcPos: 536 seqNb: 62 + LL: 2 OF: 139 ML: 3 srcPos: 541 seqNb: 63 + LL: 1 OF: 139 ML: 3 srcPos: 545 seqNb: 64 + repeat offset: 0 + LL: 0 OF: 508 ML: 4 srcPos: 549 seqNb: 65 + LL: 2 OF: 482 ML: 3 srcPos: 554 seqNb: 66 + LL: 1 OF: 127 ML: 3 srcPos: 558 seqNb: 67 + LL: 3 OF: 485 ML: 3 srcPos: 564 seqNb: 68 + LL: 0 OF: 300 ML: 3 srcPos: 567 seqNb: 69 + LL: 2 OF: 338 ML: 3 srcPos: 572 seqNb: 70 + LL: 1 OF: 285 ML: 3 srcPos: 576 seqNb: 71 + LL: 0 OF: 300 ML: 3 srcPos: 579 seqNb: 72 + repeat offset: 2 + LL: 1 OF: 60 ML: 3 srcPos: 583 seqNb: 73 + LL: 2 OF: 304 ML: 3 srcPos: 588 seqNb: 74 + LL: 2 OF: 106 ML: 3 srcPos: 593 seqNb: 75 + LL: 4 OF: 106 ML: 3 srcPos: 600 seqNb: 76 + repeat offset: 0 + LL: 2 OF: 106 ML: 3 srcPos: 605 seqNb: 77 + repeat offset: 0 + LL: 5 OF: 60 ML: 3 srcPos: 613 seqNb: 78 + repeat offset: 2 + LL: 2 OF: 594 ML: 3 srcPos: 618 seqNb: 79 + LL: 1 OF: 234 ML: 3 srcPos: 622 seqNb: 80 + LL: 1 OF: 227 ML: 3 srcPos: 626 seqNb: 81 + LL: 0 OF: 235 ML: 3 srcPos: 629 seqNb: 82 + LL: 1 OF: 311 ML: 3 srcPos: 633 seqNb: 83 + LL: 0 OF: 253 ML: 3 srcPos: 636 seqNb: 84 + LL: 1 OF: 286 ML: 3 srcPos: 640 seqNb: 85 + LL: 0 OF: 175 ML: 3 srcPos: 643 seqNb: 86 + LL: 1 OF: 395 ML: 3 srcPos: 647 seqNb: 87 + LL: 2 OF: 544 ML: 3 srcPos: 652 seqNb: 88 + LL: 0 OF: 278 ML: 3 srcPos: 655 seqNb: 89 + LL: 1 OF: 450 ML: 3 srcPos: 659 seqNb: 90 + LL: 4 OF: 469 ML: 3 srcPos: 666 seqNb: 91 + LL: 5 OF: 192 ML: 3 srcPos: 674 seqNb: 92 + LL: 0 OF: 492 ML: 3 srcPos: 677 seqNb: 93 + LL: 2 OF: 192 ML: 3 srcPos: 682 seqNb: 94 + repeat offset: 1 + LL: 2 OF: 597 ML: 3 srcPos: 687 seqNb: 95 + LL: 1 OF: 501 ML: 3 srcPos: 691 seqNb: 96 + LL: 0 OF: 148 ML: 3 srcPos: 694 seqNb: 97 + LL: 1 OF: 513 ML: 3 srcPos: 698 seqNb: 98 + LL: 0 OF: 143 ML: 3 srcPos: 701 seqNb: 99 + LL: 2 OF: 89 ML: 3 srcPos: 706 seqNb: 100 + LL: 1 OF: 513 ML: 3 srcPos: 710 seqNb: 101 + repeat offset: 2 + LL: 0 OF: 35 ML: 3 srcPos: 713 seqNb: 102 + LL: 0 OF: 218 ML: 3 srcPos: 716 seqNb: 103 + LL: 1 OF: 140 ML: 3 srcPos: 720 seqNb: 104 + LL: 2 OF: 465 ML: 3 srcPos: 725 seqNb: 105 + LL: 0 OF: 183 ML: 3 srcPos: 728 seqNb: 106 + LL: 0 OF: 704 ML: 4 srcPos: 732 seqNb: 107 + LL: 2 OF: 361 ML: 3 srcPos: 737 seqNb: 108 + LL: 1 OF: 460 ML: 3 srcPos: 741 seqNb: 109 + LL: 3 OF: 554 ML: 3 srcPos: 747 seqNb: 110 + LL: 3 OF: 544 ML: 3 srcPos: 753 seqNb: 111 + LL: 0 OF: 19 ML: 3 srcPos: 756 seqNb: 112 + LL: 2 OF: 539 ML: 3 srcPos: 761 seqNb: 113 + LL: 0 OF: 557 ML: 3 srcPos: 764 seqNb: 114 + LL: 3 OF: 501 ML: 3 srcPos: 770 seqNb: 115 + LL: 2 OF: 557 ML: 3 srcPos: 775 seqNb: 116 + repeat offset: 1 + LL: 0 OF: 683 ML: 3 srcPos: 778 seqNb: 117 + LL: 0 OF: 362 ML: 3 srcPos: 781 seqNb: 118 + LL: 1 OF: 723 ML: 4 srcPos: 786 seqNb: 119 + LL: 1 OF: 526 ML: 4 srcPos: 791 seqNb: 120 + LL: 0 OF: 653 ML: 3 srcPos: 794 seqNb: 121 + LL: 0 OF: 572 ML: 3 srcPos: 797 seqNb: 122 + LL: 1 OF: 572 ML: 3 srcPos: 801 seqNb: 123 + repeat offset: 0 + LL: 0 OF: 383 ML: 4 srcPos: 805 seqNb: 124 + LL: 4 OF: 383 ML: 4 srcPos: 813 seqNb: 125 + repeat offset: 0 + LL: 1 OF: 46 ML: 4 srcPos: 818 seqNb: 126 + LL: 0 OF: 742 ML: 3 srcPos: 821 seqNb: 127 + LL: 2 OF: 84 ML: 4 srcPos: 827 seqNb: 128 + LL: 1 OF: 793 ML: 3 srcPos: 831 seqNb: 129 + LL: 4 OF: 277 ML: 3 srcPos: 838 seqNb: 130 + LL: 0 OF: 312 ML: 3 srcPos: 841 seqNb: 131 + LL: 1 OF: 306 ML: 3 srcPos: 845 seqNb: 132 + LL: 0 OF: 706 ML: 3 srcPos: 848 seqNb: 133 + LL: 0 OF: 244 ML: 3 srcPos: 851 seqNb: 134 + LL: 4 OF: 301 ML: 3 srcPos: 858 seqNb: 135 + LL: 1 OF: 53 ML: 3 srcPos: 862 seqNb: 136 + LL: 1 OF: 313 ML: 3 srcPos: 866 seqNb: 137 + LL: 1 OF: 53 ML: 3 srcPos: 870 seqNb: 138 + repeat offset: 1 + LL: 1 OF: 301 ML: 4 srcPos: 875 seqNb: 139 + repeat offset: 2 + LL: 6 OF: 53 ML: 3 srcPos: 884 seqNb: 140 + repeat offset: 1 + LL: 3 OF: 295 ML: 3 srcPos: 890 seqNb: 141 + LL: 0 OF: 363 ML: 3 srcPos: 893 seqNb: 142 + LL: 1 OF: 742 ML: 4 srcPos: 898 seqNb: 143 + LL: 2 OF: 742 ML: 4 srcPos: 904 seqNb: 144 + repeat offset: 0 + LL: 2 OF: 728 ML: 3 srcPos: 909 seqNb: 145 + LL: 1 OF: 728 ML: 3 srcPos: 913 seqNb: 146 + repeat offset: 0 + LL: 0 OF: 597 ML: 3 srcPos: 916 seqNb: 147 + excess literals: 1 srcPos: 917 + LL type: 0 OF type: 0 ML type: 3 + number of sequences: 148 + block type: compressed + block size field: 550 + block: + block content size: 24 + last block: no + compressed block: + raw literals + literals size: 21 + total match lengths: 3 + LL: 9 OF: 905 ML: 3 srcPos: 929 seqNb: 0 + excess literals: 12 srcPos: 941 + LL type: 1 OF type: 1 ML type: 3 + number of sequences: 1 + block type: compressed + block size field: 28 + block: + block content size: 0 + last block: no + compressed block: + raw literals + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 941 + number of sequences: 0 + block type: compressed + block size field: 2 + block: + block content size: 24 + last block: no + compressed block: + raw literals + literals size: 14 + total match lengths: 10 + LL: 11 OF: 506 ML: 10 srcPos: 962 seqNb: 0 + excess literals: 3 srcPos: 965 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 22 + block: + block content size: 47 + last block: no + compressed block: + raw literals + literals size: 40 + total match lengths: 7 + LL: 40 OF: 833 ML: 4 srcPos: 1009 seqNb: 0 + LL: 0 OF: 832 ML: 3 srcPos: 1012 seqNb: 1 + repeat offset: 2 + excess literals: 0 srcPos: 1012 + LL type: 0 OF type: 0 ML type: 2 + number of sequences: 2 + block type: compressed + block size field: 53 + block: + block content size: 4 + last block: no + compressed block: + raw literals + literals size: 0 + total match lengths: 4 + LL: 0 OF: 92 ML: 4 srcPos: 1016 seqNb: 0 + excess literals: 0 srcPos: 1016 + LL type: 3 OF type: 1 ML type: 3 + number of sequences: 1 + block type: compressed + block size field: 7 + block: + block content size: 3 + last block: yes + compressed block: + raw literals + literals size: 0 + total match lengths: 3 + LL: 0 OF: 280 ML: 3 srcPos: 1019 seqNb: 0 + excess literals: 0 srcPos: 1019 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 8 + checksum: 20a07047 diff --git a/xls/modules/zstd/data/pregenerated_compressed_raw_1.zst b/xls/modules/zstd/data/pregenerated_compressed_raw_1.zst new file mode 100644 index 0000000000000000000000000000000000000000..bea909ee30ae7aae91212d16fe49be9a48dd2ede GIT binary patch literal 975 zcmV;=12Ft3wJ-g|LHh#$0000007L}U1+0te4+(PM}5`4S%4#K~0e4b!> z6np>HcPmBA)MmhAm7o|)L^$3P119i$P3cL5u^8T}Cea-+RuWxK)_f4aTK^$2r!+1h$=1w39bMDa6beP zkOV*k5ob*TZd-u45EUo0hdDnB@YM!0^G%bz+b?{A^_|Fd?z3bAJEtfQ1Jqnv4Ai_0CZe{Wd>Nt0t~Q# z=`6r*1I%myYa2jR5deMx4FC)PX#>DB3&5`cc7TBpz^Vx77XmCg0V8of@L`rwEnV{I-$Jl#*-- xp(j4Orn?{>H6Q{A6!1SU0HOgz89V?000G{M>pXq=MiB#L6R)2XmS(&lAC#4x{_}C3XNx`tMGFeX&8w1c+zUu*076B9%Bmn?;Q_lcm z93$)3o$+ygq1Dv`h!ikj{{z%2fK>ti0W2LgJ#K*f002N=!^){%+&j1gpwudWRsRz} vP@tgTAGAOh?9mp(*gOCL00C401pzk{000008~^|aVgMZg00=7pcn0~a;H*lJ literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/pregenerated_compressed_rle_1.log b/xls/modules/zstd/data/pregenerated_compressed_rle_1.log new file mode 100644 index 0000000000..6758c747f2 --- /dev/null +++ b/xls/modules/zstd/data/pregenerated_compressed_rle_1.log @@ -0,0 +1,179 @@ +seed: 1 +frame seed: 1 + frame content size: 1019 + frame window size: 294912 + content size flag: 1 + single segment flag: 0 + block: + block content size: 181 + last block: no + compressed block: + rle literals: 0xed + literals size: 139 + total match lengths: 42 + LL: 139 OF: 97 ML: 42 srcPos: 181 seqNb: 0 + excess literals: 0 srcPos: 181 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 10 + block: + block content size: 178 + last block: no + compressed block: + rle literals: 0xc6 + literals size: 21 + total match lengths: 157 + LL: 0 OF: 53 ML: 4 srcPos: 185 seqNb: 0 + LL: 0 OF: 155 ML: 3 srcPos: 188 seqNb: 1 + LL: 0 OF: 7 ML: 3 srcPos: 191 seqNb: 2 + LL: 2 OF: 124 ML: 4 srcPos: 197 seqNb: 3 + LL: 0 OF: 138 ML: 4 srcPos: 201 seqNb: 4 + LL: 0 OF: 92 ML: 4 srcPos: 205 seqNb: 5 + LL: 0 OF: 1 ML: 5 srcPos: 210 seqNb: 6 + LL: 0 OF: 93 ML: 3 srcPos: 213 seqNb: 7 + LL: 1 OF: 144 ML: 5 srcPos: 219 seqNb: 8 + LL: 1 OF: 183 ML: 4 srcPos: 224 seqNb: 9 + LL: 0 OF: 140 ML: 3 srcPos: 227 seqNb: 10 + LL: 1 OF: 42 ML: 5 srcPos: 233 seqNb: 11 + LL: 0 OF: 118 ML: 4 srcPos: 237 seqNb: 12 + LL: 1 OF: 47 ML: 4 srcPos: 242 seqNb: 13 + LL: 0 OF: 232 ML: 5 srcPos: 247 seqNb: 14 + LL: 0 OF: 24 ML: 4 srcPos: 251 seqNb: 15 + LL: 1 OF: 24 ML: 5 srcPos: 257 seqNb: 16 + repeat offset: 0 + LL: 0 OF: 2 ML: 3 srcPos: 260 seqNb: 17 + LL: 0 OF: 212 ML: 4 srcPos: 264 seqNb: 18 + LL: 1 OF: 66 ML: 4 srcPos: 269 seqNb: 19 + LL: 0 OF: 65 ML: 5 srcPos: 274 seqNb: 20 + repeat offset: 2 + LL: 0 OF: 212 ML: 5 srcPos: 279 seqNb: 21 + repeat offset: 2 + LL: 0 OF: 119 ML: 4 srcPos: 283 seqNb: 22 + LL: 1 OF: 245 ML: 4 srcPos: 288 seqNb: 23 + LL: 0 OF: 152 ML: 5 srcPos: 293 seqNb: 24 + LL: 0 OF: 219 ML: 3 srcPos: 296 seqNb: 25 + LL: 0 OF: 107 ML: 5 srcPos: 301 seqNb: 26 + LL: 0 OF: 157 ML: 4 srcPos: 305 seqNb: 27 + LL: 1 OF: 30 ML: 6 srcPos: 312 seqNb: 28 + LL: 1 OF: 44 ML: 5 srcPos: 318 seqNb: 29 + LL: 0 OF: 151 ML: 4 srcPos: 322 seqNb: 30 + LL: 1 OF: 30 ML: 4 srcPos: 327 seqNb: 31 + repeat offset: 2 + LL: 1 OF: 8 ML: 4 srcPos: 332 seqNb: 32 + LL: 1 OF: 238 ML: 4 srcPos: 337 seqNb: 33 + LL: 6 OF: 244 ML: 5 srcPos: 348 seqNb: 34 + LL: 0 OF: 290 ML: 3 srcPos: 351 seqNb: 35 + LL: 1 OF: 271 ML: 3 srcPos: 355 seqNb: 36 + LL: 0 OF: 111 ML: 4 srcPos: 359 seqNb: 37 + excess literals: 0 srcPos: 359 + LL type: 0 OF type: 2 ML type: 2 + number of sequences: 38 + block type: compressed + block size field: 80 + block: + block content size: 419 + last block: no + compressed block: + rle literals: 0xc1 + literals size: 282 + total match lengths: 137 + LL: 0 OF: 353 ML: 5 srcPos: 364 seqNb: 0 + LL: 1 OF: 111 ML: 3 srcPos: 368 seqNb: 1 + repeat offset: 1 + LL: 18 OF: 65 ML: 4 srcPos: 390 seqNb: 2 + LL: 3 OF: 213 ML: 6 srcPos: 399 seqNb: 3 + LL: 0 OF: 249 ML: 6 srcPos: 405 seqNb: 4 + LL: 11 OF: 285 ML: 11 srcPos: 427 seqNb: 5 + LL: 4 OF: 297 ML: 5 srcPos: 436 seqNb: 6 + LL: 4 OF: 61 ML: 5 srcPos: 445 seqNb: 7 + LL: 11 OF: 204 ML: 4 srcPos: 460 seqNb: 8 + LL: 7 OF: 394 ML: 3 srcPos: 470 seqNb: 9 + LL: 7 OF: 30 ML: 5 srcPos: 482 seqNb: 10 + LL: 4 OF: 346 ML: 6 srcPos: 492 seqNb: 11 + LL: 1 OF: 394 ML: 3 srcPos: 496 seqNb: 12 + repeat offset: 2 + LL: 53 OF: 501 ML: 5 srcPos: 554 seqNb: 13 + LL: 15 OF: 116 ML: 3 srcPos: 572 seqNb: 14 + LL: 5 OF: 116 ML: 3 srcPos: 580 seqNb: 15 + repeat offset: 0 + LL: 4 OF: 80 ML: 5 srcPos: 589 seqNb: 16 + LL: 32 OF: 434 ML: 3 srcPos: 624 seqNb: 17 + LL: 6 OF: 80 ML: 4 srcPos: 634 seqNb: 18 + repeat offset: 1 + LL: 3 OF: 387 ML: 4 srcPos: 641 seqNb: 19 + LL: 0 OF: 639 ML: 6 srcPos: 647 seqNb: 20 + LL: 4 OF: 319 ML: 7 srcPos: 658 seqNb: 21 + LL: 0 OF: 639 ML: 4 srcPos: 662 seqNb: 22 + repeat offset: 1 + LL: 5 OF: 387 ML: 3 srcPos: 670 seqNb: 23 + repeat offset: 2 + LL: 0 OF: 639 ML: 4 srcPos: 674 seqNb: 24 + repeat offset: 1 + LL: 5 OF: 166 ML: 3 srcPos: 682 seqNb: 25 + LL: 0 OF: 135 ML: 3 srcPos: 685 seqNb: 26 + LL: 60 OF: 91 ML: 5 srcPos: 750 seqNb: 27 + LL: 1 OF: 141 ML: 4 srcPos: 755 seqNb: 28 + LL: 0 OF: 667 ML: 5 srcPos: 760 seqNb: 29 + excess literals: 18 srcPos: 778 + LL type: 2 OF type: 0 ML type: 2 + number of sequences: 30 + block type: compressed + block size field: 80 + block: + block content size: 7 + last block: no + compressed block: + rle literals: 0x3a + literals size: 1 + total match lengths: 6 + LL: 1 OF: 282 ML: 6 srcPos: 785 seqNb: 0 + excess literals: 0 srcPos: 785 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 9 + block: + block content size: 129 + last block: no + compressed block: + rle literals: 0xcf + literals size: 60 + total match lengths: 69 + LL: 0 OF: 455 ML: 69 srcPos: 854 seqNb: 0 + excess literals: 60 srcPos: 914 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 10 + block: + block content size: 85 + last block: no + compressed block: + rle literals: 0xf1 + literals size: 76 + total match lengths: 9 + LL: 44 OF: 616 ML: 4 srcPos: 962 seqNb: 0 + LL: 11 OF: 455 ML: 5 srcPos: 978 seqNb: 1 + repeat offset: 1 + excess literals: 21 srcPos: 999 + LL type: 2 OF type: 2 ML type: 2 + number of sequences: 2 + block type: compressed + block size field: 29 + block: + block content size: 20 + last block: yes + compressed block: + rle literals: 0xf5 + literals size: 11 + total match lengths: 9 + LL: 1 OF: 118 ML: 3 srcPos: 1003 seqNb: 0 + LL: 2 OF: 709 ML: 3 srcPos: 1008 seqNb: 1 + LL: 8 OF: 168 ML: 3 srcPos: 1019 seqNb: 2 + excess literals: 0 srcPos: 1019 + LL type: 2 OF type: 2 ML type: 1 + number of sequences: 3 + block type: compressed + block size field: 24 + checksum: 043d84eb diff --git a/xls/modules/zstd/data/pregenerated_compressed_rle_1.zst b/xls/modules/zstd/data/pregenerated_compressed_rle_1.zst new file mode 100644 index 0000000000000000000000000000000000000000..ded729fd6a2d15d0e6aebe18e8623fcb8cb9c1af GIT binary patch literal 281 zcmV+!0p|WFwJ-g|LHh#$0000008{_~wFvD2R2l{&i)4fX0I9|%C?Lofsp|oNst>XR z64{kB+*fga3)Z3;@EkA5AZ>2KtFR&9fBFa)EEKpaA({ZZ#aI)_z1*X7fQ~&_Q1J40e00=0e9P9u9#RTyJs1)EYV8Gvh6F^|#`3Dq$fd2u+H2@d_1jPUV fS@i>?6o6K%0{0ISuvbx4Z7K+|R+ literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/pregenerated_compressed_rle_2.log b/xls/modules/zstd/data/pregenerated_compressed_rle_2.log new file mode 100644 index 0000000000..ed2a1dbb00 --- /dev/null +++ b/xls/modules/zstd/data/pregenerated_compressed_rle_2.log @@ -0,0 +1,103 @@ +seed: 2 +frame seed: 2 + frame content size: 152 + frame window size: 114688 + content size flag: 1 + single segment flag: 0 + block: + block content size: 91 + last block: no + compressed block: + rle literals: 0xda + literals size: 68 + total match lengths: 23 + LL: 2 OF: 1 ML: 3 srcPos: 5 seqNb: 0 + LL: 8 OF: 2 ML: 3 srcPos: 16 seqNb: 1 + LL: 5 OF: 10 ML: 4 srcPos: 25 seqNb: 2 + LL: 8 OF: 10 ML: 3 srcPos: 36 seqNb: 3 + repeat offset: 0 + LL: 4 OF: 7 ML: 3 srcPos: 43 seqNb: 4 + LL: 38 OF: 27 ML: 4 srcPos: 85 seqNb: 5 + LL: 2 OF: 68 ML: 3 srcPos: 90 seqNb: 6 + excess literals: 1 srcPos: 91 + LL type: 2 OF type: 0 ML type: 2 + number of sequences: 7 + block type: compressed + block size field: 26 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0x3c + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 91 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 61 + last block: yes + compressed block: + rle literals: 0xe1 + literals size: 56 + total match lengths: 5 + LL: 0 OF: 26 ML: 5 srcPos: 96 seqNb: 0 + excess literals: 56 srcPos: 152 + LL type: 1 OF type: 3 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 9 + checksum: 57673f5c + +seed: 2 +frame seed: 2 + frame content size: 152 + frame window size: 114688 + content size flag: 1 + single segment flag: 0 + block: + block content size: 91 + last block: no + compressed block: + rle literals: 0xda + literals size: 68 + total match lengths: 23 + LL: 2 OF: 1 ML: 3 srcPos: 5 seqNb: 0 + LL: 8 OF: 2 ML: 3 srcPos: 16 seqNb: 1 + LL: 5 OF: 10 ML: 4 srcPos: 25 seqNb: 2 + LL: 8 OF: 10 ML: 3 srcPos: 36 seqNb: 3 + repeat offset: 0 + LL: 4 OF: 7 ML: 3 srcPos: 43 seqNb: 4 + LL: 38 OF: 27 ML: 4 srcPos: 85 seqNb: 5 + LL: 2 OF: 68 ML: 3 srcPos: 90 seqNb: 6 + excess literals: 1 srcPos: 91 + LL type: 2 OF type: 0 ML type: 2 + number of sequences: 7 + block type: compressed + block size field: 26 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0x3c + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 91 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 61 + last block: yes + compressed block: + rle literals: 0xe1 + literals size: 56 + total match lengths: 5 + LL: 0 OF: 26 ML: 5 srcPos: 96 seqNb: 0 + excess literals: 56 srcPos: 152 + LL type: 1 OF type: 3 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 9 + checksum: 57673f5c diff --git a/xls/modules/zstd/data/pregenerated_compressed_rle_2.zst b/xls/modules/zstd/data/pregenerated_compressed_rle_2.zst new file mode 100644 index 0000000000000000000000000000000000000000..d9d78e4a9a66fa237bdf8a75d701f7c4d4840907 GIT binary patch literal 61 zcmdPcs{gmeYz6}Z!xaVwSC(7s9Rfy;8&^D?&s-qy-cUPaq7IAX}0Nr&ASO5S3 literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.log b/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.log new file mode 100644 index 0000000000..a785b43a08 --- /dev/null +++ b/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.log @@ -0,0 +1,25 @@ +seed: 422473 +frame seed: 422473 + frame content size: 25 + frame window size: 5632 + content size flag: 1 + single segment flag: 0 + block: + block content size: 25 + last block: yes + compressed block: + raw literals + literals size: 11 + total match lengths: 14 + LL: 1 OF: 1 ML: 3 srcPos: 4 seqNb: 0 + LL: 0 OF: 3 ML: 4 srcPos: 8 seqNb: 1 + LL: 10 OF: 3 ML: 4 srcPos: 22 seqNb: 2 + repeat offset: 0 + LL: 0 OF: 1 ML: 3 srcPos: 25 seqNb: 3 + repeat offset: 2 + excess literals: 0 srcPos: 25 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 4 + block type: compressed + block size field: 23 + checksum: 335a35eb diff --git a/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.zst b/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_422473.zst new file mode 100644 index 0000000000000000000000000000000000000000..07ac1493f58207b329213e3034f212774fa3a689 GIT binary patch literal 40 wcmdPcs{gk|SdxK(VJ`ziM1|SyHl6ksf765cEDU-K0xP%~4#YCPHjOd{00iRQU(Tx?_c=7UlTpn&%$8bUcj#XO+rT6+Pi_@% literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.log b/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.log new file mode 100644 index 0000000000..672a98a312 --- /dev/null +++ b/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.log @@ -0,0 +1,21 @@ +seed: 462302 +frame seed: 462302 + frame content size: 27 + frame window size: 11264 + content size flag: 1 + single segment flag: 0 + block: + block content size: 27 + last block: yes + compressed block: + raw literals + literals size: 6 + total match lengths: 21 + LL: 1 OF: 1 ML: 18 srcPos: 19 seqNb: 0 + LL: 5 OF: 16 ML: 3 srcPos: 27 seqNb: 1 + excess literals: 0 srcPos: 27 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 2 + block type: compressed + block size field: 14 + checksum: 8eb0243a diff --git a/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.zst b/xls/modules/zstd/data/raw_literals_predefined_sequences_seed_462302.zst new file mode 100644 index 0000000000000000000000000000000000000000..1f38ecd40da94b5837533ca2424f9f15528ab8df GIT binary patch literal 31 mcmdPcs{gk|TAG1@p_GBapd~6~ZcsZDgE8aL;v6fL4SfKSG6{zO literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.log b/xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.log new file mode 100644 index 0000000000..769fcf02cd --- /dev/null +++ b/xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.log @@ -0,0 +1,20 @@ +seed: 700216 +frame seed: 700216 + frame content size: 21 + frame window size: 2097152 + content size flag: 1 + single segment flag: 0 + block: + block content size: 21 + last block: yes + compressed block: + raw literals + literals size: 18 + total match lengths: 3 + LL: 18 OF: 1 ML: 3 srcPos: 21 seqNb: 0 + excess literals: 0 srcPos: 21 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 25 + checksum: 46d2ac93 diff --git a/xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.zst b/xls/modules/zstd/data/raw_literals_rle_sequences_seed_700216.zst new file mode 100644 index 0000000000000000000000000000000000000000..541f7860abfbb436f4ad70a20656426405511957 GIT binary patch literal 46 ycmdPcs{i*$geU_9oMm8`Q2#~IR#~s&Qp!c2KMrZ9k6d(N3=w2v;F!GTk{bYQNf43% literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.log b/xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.log new file mode 100644 index 0000000000..ddd13d1a38 --- /dev/null +++ b/xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.log @@ -0,0 +1,87 @@ +seed: 701326 +frame seed: 701326 + frame content size: 28 + frame window size: 11264 + content size flag: 1 + single segment flag: 0 + block: + block content size: 1 + last block: no + compressed block: + rle literals: 0xf3 + literals size: 1 + total match lengths: 0 + excess literals: 1 srcPos: 1 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 3 + last block: no + compressed block: + rle literals: 0x08 + literals size: 3 + total match lengths: 0 + excess literals: 3 srcPos: 4 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 18 + last block: no + compressed block: + rle literals: 0x62 + literals size: 7 + total match lengths: 11 + LL: 0 OF: 1 ML: 3 srcPos: 7 seqNb: 0 + LL: 4 OF: 11 ML: 8 srcPos: 19 seqNb: 1 + excess literals: 3 srcPos: 22 + LL type: 2 OF type: 2 ML type: 2 + number of sequences: 2 + block type: compressed + block size field: 22 + block: + block content size: 2 + last block: no + compressed block: + rle literals: 0x90 + literals size: 2 + total match lengths: 0 + excess literals: 2 srcPos: 24 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0xfd + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 24 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 1 + last block: no + compressed block: + rle literals: 0xab + literals size: 1 + total match lengths: 0 + excess literals: 1 srcPos: 25 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 3 + last block: yes + compressed block: + rle literals: 0x2d + literals size: 3 + total match lengths: 0 + excess literals: 3 srcPos: 28 + number of sequences: 0 + block type: compressed + block size field: 3 + checksum: 08dc0268 diff --git a/xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.zst b/xls/modules/zstd/data/rle_literals_compressed_sequences_seed_701326.zst new file mode 100644 index 0000000000000000000000000000000000000000..23f21c7ce7ad473eba27d42293af286ab54c0485 GIT binary patch literal 75 zcmdPcs{gk|T84pv0f;$2gGfmZhAj*XmPt%2L<|o67Y=w}FJh4JkJ*fYhk*qsEjR(B Ui19C2!)gXupaxxr45m9A0E&kX+W-In literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.log b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.log new file mode 100644 index 0000000000..ac01d5ea38 --- /dev/null +++ b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.log @@ -0,0 +1,37 @@ +seed: 406229 +frame seed: 406229 + frame content size: 83 + frame window size: 57344 + content size flag: 1 + single segment flag: 0 + block: + block content size: 76 + last block: no + compressed block: + rle literals: 0xba + literals size: 49 + total match lengths: 27 + LL: 1 OF: 1 ML: 6 srcPos: 7 seqNb: 0 + LL: 14 OF: 16 ML: 4 srcPos: 25 seqNb: 1 + LL: 15 OF: 27 ML: 4 srcPos: 44 seqNb: 2 + LL: 5 OF: 16 ML: 4 srcPos: 53 seqNb: 3 + repeat offset: 1 + LL: 14 OF: 23 ML: 6 srcPos: 73 seqNb: 4 + LL: 0 OF: 20 ML: 3 srcPos: 76 seqNb: 5 + excess literals: 0 srcPos: 76 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 6 + block type: compressed + block size field: 19 + block: + block content size: 7 + last block: yes + compressed block: + rle literals: 0x27 + literals size: 7 + total match lengths: 0 + excess literals: 7 srcPos: 83 + number of sequences: 0 + block type: compressed + block size field: 3 + checksum: e20e662f diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.zst b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_406229.zst new file mode 100644 index 0000000000000000000000000000000000000000..5886d2796cec029257ee5564a2c1505a295d5ec8 GIT binary patch literal 42 ycmdPcs{gk|FPMRWVGaX>DDy5h26M&*#Z#nbonMj8mRb-l%fMi%&Y+*h_Xq$A77Qr> literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.log b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.log new file mode 100644 index 0000000000..8bc1fedfa2 --- /dev/null +++ b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.log @@ -0,0 +1,28 @@ +seed: 411034 +frame seed: 411034 + frame content size: 31 + frame window size: 31 + content size flag: 1 + single segment flag: 1 + block: + block content size: 31 + last block: yes + compressed block: + rle literals: 0x25 + literals size: 1 + total match lengths: 30 + LL: 1 OF: 1 ML: 8 srcPos: 9 seqNb: 0 + LL: 0 OF: 1 ML: 3 srcPos: 12 seqNb: 1 + LL: 0 OF: 5 ML: 6 srcPos: 18 seqNb: 2 + LL: 0 OF: 10 ML: 3 srcPos: 21 seqNb: 3 + LL: 0 OF: 5 ML: 4 srcPos: 25 seqNb: 4 + repeat offset: 1 + LL: 0 OF: 10 ML: 3 srcPos: 28 seqNb: 5 + repeat offset: 1 + LL: 0 OF: 1 ML: 3 srcPos: 31 seqNb: 6 + excess literals: 0 srcPos: 31 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 7 + block type: compressed + block size field: 19 + checksum: 1cc9a33c diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.zst b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_411034.zst new file mode 100644 index 0000000000000000000000000000000000000000..08d368a59b26c379cd54fe05b890118dd0956afe GIT binary patch literal 35 ocmdPcs{eP1JOcy6Tm}YCRdxmoAd_POE5j)uOW+-s&Ek_X0Fqb;QUCw| literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.log b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.log new file mode 100644 index 0000000000..562e10ee40 --- /dev/null +++ b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.log @@ -0,0 +1,53 @@ +seed: 413015 +frame seed: 413015 + frame content size: 86 + frame window size: 86 + content size flag: 1 + single segment flag: 1 + block: + block content size: 48 + last block: no + compressed block: + rle literals: 0x89 + literals size: 35 + total match lengths: 13 + LL: 35 OF: 22 ML: 10 srcPos: 45 seqNb: 0 + LL: 0 OF: 37 ML: 3 srcPos: 48 seqNb: 1 + excess literals: 0 srcPos: 48 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 2 + block type: compressed + block size field: 11 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0xa8 + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 48 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 38 + last block: yes + compressed block: + rle literals: 0x25 + literals size: 12 + total match lengths: 26 + LL: 0 OF: 24 ML: 3 srcPos: 51 seqNb: 0 + LL: 1 OF: 40 ML: 3 srcPos: 55 seqNb: 1 + LL: 11 OF: 37 ML: 4 srcPos: 70 seqNb: 2 + LL: 0 OF: 5 ML: 3 srcPos: 73 seqNb: 3 + LL: 0 OF: 40 ML: 3 srcPos: 76 seqNb: 4 + LL: 0 OF: 70 ML: 3 srcPos: 79 seqNb: 5 + LL: 0 OF: 74 ML: 3 srcPos: 82 seqNb: 6 + LL: 0 OF: 40 ML: 4 srcPos: 86 seqNb: 7 + repeat offset: 2 + excess literals: 0 srcPos: 86 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 8 + block type: compressed + block size field: 24 + checksum: 9f8a30e7 diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.zst b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_413015.zst new file mode 100644 index 0000000000000000000000000000000000000000..209ef6617839bac20f9102a4ec76721e9caeed48 GIT binary patch literal 64 zcmdPcs{i*%7y|^vFff=hbuuw{FmAZ>Ojw42fpG=HQ3i%YRSpKd1~x_y0|sx#1}27; Q2c|PsG-k3sH|UxV0Q)Qu>;M1& literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.log b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.log new file mode 100644 index 0000000000..adcc599156 --- /dev/null +++ b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.log @@ -0,0 +1,34 @@ +seed: 436165 +frame seed: 436165 + frame content size: 90 + frame window size: 589824 + content size flag: 1 + single segment flag: 0 + block: + block content size: 1 + last block: no + compressed block: + rle literals: 0x88 + literals size: 1 + total match lengths: 0 + excess literals: 1 srcPos: 1 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 89 + last block: yes + compressed block: + rle literals: 0x65 + literals size: 51 + total match lengths: 38 + LL: 4 OF: 1 ML: 5 srcPos: 10 seqNb: 0 + LL: 23 OF: 3 ML: 5 srcPos: 38 seqNb: 1 + LL: 2 OF: 4 ML: 6 srcPos: 46 seqNb: 2 + LL: 9 OF: 33 ML: 22 srcPos: 77 seqNb: 3 + excess literals: 13 srcPos: 90 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 4 + block type: compressed + block size field: 15 + checksum: 391cc8a2 diff --git a/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.zst b/xls/modules/zstd/data/rle_literals_predefined_sequences_seed_436165.zst new file mode 100644 index 0000000000000000000000000000000000000000..1eb90bcec4c7709120731752e030407228765130 GIT binary patch literal 38 ucmdPcs{gmeGm3$ML56{WvxA|Qfx(nHm4(4&cZvF;>AzjJge0Zvp56 BI`IGi literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.log b/xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.log new file mode 100644 index 0000000000..d80c261dc5 --- /dev/null +++ b/xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.log @@ -0,0 +1,111 @@ +seed: 408158 +frame seed: 408158 + frame content size: 44 + frame window size: 90112 + content size flag: 1 + single segment flag: 0 + block: + block content size: 43 + last block: no + compressed block: + raw literals + literals size: 15 + total match lengths: 28 + LL: 7 OF: 3 ML: 9 srcPos: 16 seqNb: 0 + LL: 0 OF: 2 ML: 4 srcPos: 20 seqNb: 1 + LL: 0 OF: 12 ML: 3 srcPos: 23 seqNb: 2 + LL: 8 OF: 6 ML: 12 srcPos: 43 seqNb: 3 + excess literals: 0 srcPos: 43 + LL type: 0 OF type: 0 ML type: 0 + number of sequences: 4 + block type: compressed + block size field: 27 + block: + block content size: 1 + last block: no + compressed block: + raw literals + literals size: 1 + total match lengths: 0 + excess literals: 1 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 0 + last block: no + compressed block: + raw literals + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 2 + block: + block content size: 0 + last block: no + compressed block: + raw literals + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 2 + block: + block content size: 0 + last block: no + compressed block: + raw literals + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 2 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0x57 + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0x02 + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 0 + last block: no + compressed block: + rle literals: 0x96 + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 3 + block: + block content size: 0 + last block: yes + compressed block: + rle literals: 0x40 + literals size: 0 + total match lengths: 0 + excess literals: 0 srcPos: 44 + number of sequences: 0 + block type: compressed + block size field: 3 + checksum: 975ba214 diff --git a/xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.zst b/xls/modules/zstd/data/rle_raw_literals_predefined_sequences_seed_408158.zst new file mode 100644 index 0000000000000000000000000000000000000000..ddb555d1ec10bedcdae94e207d616c656badb7e6 GIT binary patch literal 93 zcmdPcs{i+hu?_=t^LcVPI%9WSGLp@SE9#ff)?ne`o*ypYiW+zWX4( q6Ap>Y{#h$vrC#xHLX*h!kBoc_0_QezI~g&`GB7yaVCcHpI}ZR{058%2 literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.log b/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.log new file mode 100644 index 0000000000..2e7d1110a7 --- /dev/null +++ b/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.log @@ -0,0 +1,46 @@ +seed: 400025 +frame seed: 400025 + frame content size: 142 + frame window size: 40960 + content size flag: 1 + single segment flag: 0 + block: + block content size: 78 + last block: no + compressed block: + compressed literals + small range literals + huffman log: 4 + regenerated size: 66 + compressed size: 50 + literals size: 66 + total match lengths: 12 + LL: 66 OF: 45 ML: 12 srcPos: 78 seqNb: 0 + excess literals: 0 srcPos: 78 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 60 + block: + block content size: 64 + last block: yes + compressed block: + compressed literals + huffman repeat stats + regenerated size: 43 + compressed size: 30 + literals size: 43 + total match lengths: 21 + LL: 12 OF: 17 ML: 3 srcPos: 93 seqNb: 0 + LL: 0 OF: 65 ML: 5 srcPos: 98 seqNb: 1 + LL: 23 OF: 7 ML: 3 srcPos: 124 seqNb: 2 + LL: 4 OF: 65 ML: 4 srcPos: 132 seqNb: 3 + repeat offset: 1 + LL: 0 OF: 69 ML: 3 srcPos: 135 seqNb: 4 + LL: 1 OF: 75 ML: 3 srcPos: 139 seqNb: 5 + excess literals: 3 srcPos: 142 + LL type: 2 OF type: 2 ML type: 0 + number of sequences: 6 + block type: compressed + block size field: 60 + checksum: 29af0a62 diff --git a/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.zst b/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.zst new file mode 100644 index 0000000000000000000000000000000000000000..884f540c77e2e215f227606c3a7c765a36e17064 GIT binary patch literal 140 zcmdPcs{gk|tB-+!;Rz#yS_@B~AOr|-GJxRI1Jl!v9SCQT3|0SaF)!<*wzSPpf%m${ zRwM`y literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.log b/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.log new file mode 100644 index 0000000000..6f5e6bf708 --- /dev/null +++ b/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.log @@ -0,0 +1,81 @@ +seed: 400061 +frame seed: 400061 + frame content size: 241 + frame window size: 2048 + content size flag: 1 + single segment flag: 0 + block: + block content size: 60 + last block: no + compressed block: + raw literals + literals size: 60 + total match lengths: 0 + excess literals: 60 srcPos: 60 + number of sequences: 0 + block type: compressed + block size field: 63 + block: + block content size: 91 + last block: no + compressed block: + compressed literals + small range literals + huffman log: 10 + regenerated size: 44 + compressed size: 39 + literals size: 44 + total match lengths: 47 + LL: 1 OF: 40 ML: 3 srcPos: 64 seqNb: 0 + LL: 0 OF: 12 ML: 3 srcPos: 67 seqNb: 1 + LL: 2 OF: 13 ML: 3 srcPos: 72 seqNb: 2 + LL: 0 OF: 70 ML: 3 srcPos: 75 seqNb: 3 + LL: 8 OF: 71 ML: 3 srcPos: 86 seqNb: 4 + LL: 17 OF: 17 ML: 3 srcPos: 106 seqNb: 5 + LL: 0 OF: 39 ML: 3 srcPos: 109 seqNb: 6 + LL: 0 OF: 56 ML: 3 srcPos: 112 seqNb: 7 + LL: 1 OF: 78 ML: 5 srcPos: 118 seqNb: 8 + LL: 1 OF: 48 ML: 3 srcPos: 122 seqNb: 9 + LL: 0 OF: 122 ML: 3 srcPos: 125 seqNb: 10 + LL: 1 OF: 1 ML: 3 srcPos: 129 seqNb: 11 + LL: 7 OF: 31 ML: 4 srcPos: 140 seqNb: 12 + LL: 3 OF: 19 ML: 5 srcPos: 148 seqNb: 13 + excess literals: 3 srcPos: 151 + LL type: 2 OF type: 0 ML type: 2 + number of sequences: 14 + block type: compressed + block size field: 74 + block: + block content size: 11 + last block: no + compressed block: + rle literals: 0x9c + literals size: 8 + total match lengths: 3 + LL: 4 OF: 1 ML: 3 srcPos: 158 seqNb: 0 + repeat offset: 2 + excess literals: 4 srcPos: 162 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 8 + block: + block content size: 79 + last block: yes + compressed block: + compressed literals + huffman repeat stats + regenerated size: 57 + compressed size: 37 + literals size: 57 + total match lengths: 22 + LL: 22 OF: 18 ML: 3 srcPos: 187 seqNb: 0 + LL: 7 OF: 168 ML: 5 srcPos: 199 seqNb: 1 + LL: 28 OF: 48 ML: 5 srcPos: 232 seqNb: 2 + LL: 0 OF: 176 ML: 9 srcPos: 241 seqNb: 3 + excess literals: 0 srcPos: 241 + LL type: 2 OF type: 0 ML type: 2 + number of sequences: 4 + block type: compressed + block size field: 69 + checksum: 1d05f549 diff --git a/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.zst b/xls/modules/zstd/data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.zst new file mode 100644 index 0000000000000000000000000000000000000000..b0fe4849b33e414c3f433a607ba487e6d9d3ac45 GIT binary patch literal 244 zcmdPcs{i*0$43ST_`}F>g!xjNTiEi28&i!Jzum35@8Qy_?Cp09l1{rE`u}(4%Uj!S zZE;c#b$fVoj%U<YWcpoa_xNa^A+Eeg1;EnQ$xD{r2Ve0yl(u1xf{eU}5)(k8r)} z!oc7-hcSeOk%3v4iD9}kCkF!vF8m&;v7ckT)PjG7UK?B{$xXI-7P5ElKJma!6AC6S oXJqLR(MVus{lm)kgIz?UVL#)4Mq}n>X{kZHGgz5Czp}~#0A!C~PXGV_ literal 0 HcmV?d00001 diff --git a/xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.log b/xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.log new file mode 100644 index 0000000000..9962123a00 --- /dev/null +++ b/xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.log @@ -0,0 +1,53 @@ +seed: 403927 +frame seed: 403927 + frame content size: 224 + frame window size: 229376 + content size flag: 1 + single segment flag: 0 + block: + block content size: 100 + last block: no + compressed block: + compressed literals + distribution weight: 46% + huffman log: 8 + regenerated size: 67 + compressed size: 56 + literals size: 67 + total match lengths: 33 + LL: 67 OF: 46 ML: 33 srcPos: 100 seqNb: 0 + excess literals: 0 srcPos: 100 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 68 + block: + block content size: 23 + last block: no + compressed block: + rle literals: 0x46 + literals size: 14 + total match lengths: 9 + LL: 14 OF: 27 ML: 9 srcPos: 123 seqNb: 0 + excess literals: 0 srcPos: 123 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 8 + block: + block content size: 101 + last block: yes + compressed block: + compressed literals + huffman repeat stats + regenerated size: 96 + compressed size: 29 + literals size: 96 + total match lengths: 5 + LL: 0 OF: 4 ML: 5 srcPos: 128 seqNb: 0 + excess literals: 96 srcPos: 224 + LL type: 1 OF type: 1 ML type: 1 + number of sequences: 1 + block type: compressed + block size field: 38 + checksum: d06e892b diff --git a/xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.zst b/xls/modules/zstd/data/treeless_huffman_literals_rle_sequences_seed_403927.zst new file mode 100644 index 0000000000000000000000000000000000000000..d5cfe6c706ba9b984dbb80eb547409ab0c657773 GIT binary patch literal 137 zcmV;40CxW;~PIEbq8P;~|)RcEED@K9BF`Vj^I z2LJ{DQ+IGAWC_bi4TLIG11E0-sbK*P2Vt`%1OZeT1s+2TL;wJBMgdd~1O^^80RRI= r2UU_#uF#0^gp^g{SLC4)DJ6zfw|q|#!&$3=5 Date: Wed, 23 Jul 2025 14:36:26 +0200 Subject: [PATCH 18/30] Collect P&R benchmarks Signed-off-by: Robert Winkler --- xls/modules/zstd/BUILD | 45 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 9dff798ed4..04e9373c8b 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -15,7 +15,7 @@ # Build rules for XLS ZSTD codec implementation. # pytype binary, library -load("@rules_hdl//place_and_route:build_defs.bzl", "place_and_route") +load("@rules_hdl//place_and_route:build_defs.bzl", "collect_benchmark_reports", "place_and_route") load("@rules_hdl//synthesis:build_defs.bzl", "benchmark_synth", "synthesize_rtl") load("@rules_hdl//verilog:providers.bzl", "verilog_library") load("@xls_pip_deps//:requirements.bzl", "requirement") @@ -3846,3 +3846,46 @@ xls_dslx_test( name = "refilling_shift_buffer_mux_dslx_test", library = ":refilling_shift_buffer_mux_dslx", ) + +collect_benchmark_reports( + name = "all_banchmark_reports", + srcs = [ + ":window_buffer_place_and_route", + ":shift_buffer_aligner_place_and_route", + ":shift_buffer_storage_place_and_route", + ":shift_buffer_place_and_route", + ":frame_header_dec_place_and_route", + ":block_header_dec_place_and_route", + ":raw_block_dec_place_and_route", + ":rle_block_dec_place_and_route", + ":dec_mux_place_and_route", + ":sequence_executor_place_and_route", + ":axi_csr_accessor_place_and_route", + ":csr_config_place_and_route", + ":ram_rw_handler_place_and_route", + ":fse_proba_freq_dec_place_and_route", + ":refilling_shift_buffer_internal_place_and_route", + ":zstd_dec_internal_place_and_route", + ":fse_table_iterator_place_and_route", + ":fse_table_creator_place_and_route", + ":command_constructor_place_and_route", + ":ram_demux_place_and_route", + ":ram_demux_naive_place_and_route", + ":fse_dec_place_and_route", + ":ram_demux3_place_and_route", + ":rle_literals_dec_place_and_route", + ":raw_literals_dec_place_and_route", + ":literals_buffer_place_and_route", + ":literals_decoder_ctrl_place_and_route", + # ":literals_decoder_place_and_route", + ":huffman_prescan_place_and_route", + # ":huffman_code_builder_place_and_route", + ":huffman_axi_reader_place_and_route", + # ":huffman_data_preprocessor_place_and_route", + # ":huffman_decoder_place_and_route", + ":huffman_ctrl_place_and_route", + ":huffman_weights_dec_place_and_route", + # ":huffman_literals_dec_place_and_route", + # ":zstd_dec_place_and_route", + ] +) From e49a052112b954743de955c9bd4f7747ae841fc2 Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Tue, 17 Jun 2025 10:41:35 +0200 Subject: [PATCH 19/30] Add fixed version of RamDemux together with a test Signed-off-by: Robert Winkler --- xls/modules/zstd/BUILD | 34 ++++- xls/modules/zstd/ram_demux_cocotb_test.py | 173 ++++++++++++++++++++++ xls/modules/zstd/rtl/BUILD | 3 +- xls/modules/zstd/rtl/ram_demux_wrapper.v | 155 +++++++++++++++++++ 4 files changed, 363 insertions(+), 2 deletions(-) create mode 100644 xls/modules/zstd/ram_demux_cocotb_test.py create mode 100644 xls/modules/zstd/rtl/ram_demux_wrapper.v diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 04e9373c8b..82449a54ba 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -2213,6 +2213,7 @@ RAM_DEMUX_CODEGEN_ARGS = { "clock_period_ps": "750", "reset": "rst", "use_system_verilog": "false", + "streaming_channel_data_suffix": "_data", "materialize_internal_fifos": "true", } @@ -2290,6 +2291,37 @@ ram_demux_naive_codegen_args = { "materialize_internal_fifos": "true", } +py_test( + name = "ram_demux_cocotb_test", + srcs = ["ram_demux_cocotb_test.py"], + data = [ + "//xls/modules/zstd:ram_demux.v", + "//xls/modules/zstd/rtl:ram_1r1w.v", + "//xls/modules/zstd/rtl:ram_demux_wrapper.v", + "@com_icarus_iverilog//:iverilog", + "@com_icarus_iverilog//:vvp", + ], + env = { + "BUILD_WORKING_DIRECTORY": "sim_build", + "PYTHONUNBUFFERED": "1", + }, + imports = ["."], + tags = ["manual"], + visibility = ["//xls:xls_users"], + deps = [ + requirement("cocotb"), + requirement("cocotbext-axi"), + requirement("pytest"), + requirement("zstandard"), + "//xls/common:runfiles", + "//xls/modules/zstd/cocotb:channel", + "//xls/modules/zstd/cocotb:data_generator", + "//xls/modules/zstd/cocotb:memory", + "//xls/modules/zstd/cocotb:utils", + "//xls/modules/zstd/cocotb:xlsstruct", + ], +) + xls_dslx_verilog( name = "ram_demux_naive_verilog", codegen_args = ram_demux_naive_codegen_args, @@ -3887,5 +3919,5 @@ collect_benchmark_reports( ":huffman_weights_dec_place_and_route", # ":huffman_literals_dec_place_and_route", # ":zstd_dec_place_and_route", - ] + ], ) diff --git a/xls/modules/zstd/ram_demux_cocotb_test.py b/xls/modules/zstd/ram_demux_cocotb_test.py new file mode 100644 index 0000000000..5e75c6abce --- /dev/null +++ b/xls/modules/zstd/ram_demux_cocotb_test.py @@ -0,0 +1,173 @@ +# Copyright 2024 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import pathlib +import random +import sys +import warnings + +import cocotb +from cocotb.binary import BinaryValue +from cocotb.clock import Clock +from cocotb.triggers import Event, ClockCycles, RisingEdge +from cocotb_bus.scoreboard import Scoreboard +from cocotbext.axi import axi_channels +from cocotbext.axi.axi_ram import AxiRamRead +from cocotbext.axi.sparse_memory import SparseMemory + +import xls.modules.zstd.cocotb.channel as xlschannel +from xls.modules.zstd.cocotb import utils +from xls.modules.zstd.cocotb import xlsstruct + +warnings.filterwarnings("ignore", category=DeprecationWarning) + +ADDR_W = 10 +DATA_W = 64 +NUM_PARTITIONS = 64 +SEL_W = 1 + + +@xlsstruct.xls_dataclass +class SelReq(xlsstruct.XLSStruct): + sel: SEL_W + + +@xlsstruct.xls_dataclass +class ReadReq(xlsstruct.XLSStruct): + addr: ADDR_W + mask: NUM_PARTITIONS + + +@xlsstruct.xls_dataclass +class ReadResp(xlsstruct.XLSStruct): + data: DATA_W + + +@xlsstruct.xls_dataclass +class WriteReq(xlsstruct.XLSStruct): + addr: ADDR_W + data: DATA_W + mask: NUM_PARTITIONS + + +@xlsstruct.xls_dataclass +class WriteResp(xlsstruct.XLSStruct): + pass + + +def print_callback(name: str = "monitor"): + def _print_callback(transaction): + print(f" [{name}]: {transaction}") + + return _print_callback + + +def set_termination_event(monitor, event, transactions): + def terminate_cb(_): + if monitor.stats.received_transactions == transactions: + print("all transactions received") + event.set() + + monitor.add_callback(terminate_cb) + + +@cocotb.test(timeout_time=500, timeout_unit="ms") +async def test_mem_reader(dut): + + clock = Clock(dut.clk, 10, units="us") + cocotb.start_soon(clock.start()) + + sel_resp_channel = xlschannel.XLSChannel(dut, "ram_demux__sel_resp_s", dut.clk) + rd_resp_channel = xlschannel.XLSChannel(dut, "ram_demux__rd_resp_s", dut.clk) + wr_resp_channel = xlschannel.XLSChannel( + dut, "ram_demux__wr_resp_s", dut.clk, start_now=True + ) + + sel_driver = xlschannel.XLSChannelDriver(dut, "ram_demux__sel_req_r", dut.clk) + rd_req_driver = xlschannel.XLSChannelDriver(dut, "ram_demux__rd_req_r", dut.clk) + wr_req_driver = xlschannel.XLSChannelDriver(dut, "ram_demux__wr_req_r", dut.clk) + + dut.rst.setimmediatevalue(0) + await ClockCycles(dut.clk, 10) + dut.rst.setimmediatevalue(1) + await ClockCycles(dut.clk, 10) + dut.rst.setimmediatevalue(0) + + sel_resp_channel.rdy.setimmediatevalue(1) + rd_resp_channel.rdy.setimmediatevalue(1) + wr_resp_channel.rdy.setimmediatevalue(1) + + await sel_driver.send(SelReq(0)) + while True: + await RisingEdge(dut.clk) + if sel_resp_channel.rdy.value and sel_resp_channel.vld.value: + break + + await wr_req_driver.send(WriteReq(addr=123, data=0x10, mask=0xFFFF_FFFF_FFFF_FFFF)) + while True: + await RisingEdge(dut.clk) + if wr_resp_channel.rdy.value and wr_resp_channel.vld.value: + break + + await sel_driver.send(SelReq(1)) + while True: + await RisingEdge(dut.clk) + if sel_resp_channel.rdy.value and sel_resp_channel.vld.value: + break + + await wr_req_driver.send(WriteReq(addr=256, data=0x3, mask=0xFFFF_FFFF_FFFF_FFFF)) + while True: + await RisingEdge(dut.clk) + if wr_resp_channel.rdy.value and wr_resp_channel.vld.value: + break + + await sel_driver.send(SelReq(0)) + while True: + await RisingEdge(dut.clk) + if sel_resp_channel.rdy.value and sel_resp_channel.vld.value: + break + + await rd_req_driver.send(ReadReq(addr=123, mask=0xFFFF_FFFF_FFFF_FFFF)) + while True: + await RisingEdge(dut.clk) + if rd_resp_channel.rdy.value and rd_resp_channel.vld.value: + assert rd_resp_channel.data.value == 0x10 + break + + await sel_driver.send(SelReq(1)) + while True: + await RisingEdge(dut.clk) + if sel_resp_channel.rdy.value and sel_resp_channel.vld.value: + break + + await rd_req_driver.send(ReadReq(addr=256, mask=0xFFFF_FFFF_FFFF_FFFF)) + while True: + await RisingEdge(dut.clk) + if rd_resp_channel.rdy.value and rd_resp_channel.vld.value: + assert rd_resp_channel.data.value == 0x3 + break + + +if __name__ == "__main__": + sys.path.append(str(pathlib.Path(__file__).parent)) + + toplevel = "ram_demux_wrapper" + verilog_sources = [ + "xls/modules/zstd/ram_demux.v", + "xls/modules/zstd/rtl/ram_1r1w.v", + "xls/modules/zstd/rtl/ram_demux_wrapper.v", + ] + test_module = [pathlib.Path(__file__).stem] + utils.run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/rtl/BUILD b/xls/modules/zstd/rtl/BUILD index 3816de3b42..1a6c5f1592 100644 --- a/xls/modules/zstd/rtl/BUILD +++ b/xls/modules/zstd/rtl/BUILD @@ -36,7 +36,8 @@ exports_files( [ "zstd_dec_wrapper.sv", "xls_fifo_wrapper.sv", - "ram_1r1w.v" + "ram_demux_wrapper.v", + "ram_1r1w.v", ], ) diff --git a/xls/modules/zstd/rtl/ram_demux_wrapper.v b/xls/modules/zstd/rtl/ram_demux_wrapper.v new file mode 100644 index 0000000000..973b0b18a4 --- /dev/null +++ b/xls/modules/zstd/rtl/ram_demux_wrapper.v @@ -0,0 +1,155 @@ +// Copyright 2025 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module ram_demux_wrapper #( + parameter DATA_WIDTH = 64, + parameter SIZE = 1024, + parameter ADDR_WIDTH = $clog2(SIZE), + parameter NUM_PARTITIONS = 64 +) ( + input wire clk, + input wire rst, + + input wire ram_demux__sel_req_r_data, + input wire ram_demux__sel_req_r_vld, + output wire ram_demux__sel_req_r_rdy, + + input wire ram_demux__sel_resp_s_rdy, + output wire ram_demux__sel_resp_s_vld, + + input wire [ NUM_PARTITIONS + ADDR_WIDTH - 1:0 ] ram_demux__rd_req_r_data, + input wire ram_demux__rd_req_r_vld, + output wire ram_demux__rd_req_r_rdy, + + output wire [ DATA_WIDTH -1:0 ] ram_demux__rd_resp_s_data, + output wire ram_demux__rd_resp_s_vld, + input wire ram_demux__rd_resp_s_rdy, + + input wire [ DATA_WIDTH + NUM_PARTITIONS + ADDR_WIDTH -1:0 ] ram_demux__wr_req_r_data, + input wire ram_demux__wr_req_r_vld, + output wire ram_demux__wr_req_r_rdy, + + input wire ram_demux__wr_resp_s_rdy, + output wire ram_demux__wr_resp_s_vld +); + +wire [ DATA_WIDTH -1:0 ] ram0_wr_data; +wire [ ADDR_WIDTH -1:0 ] ram0_wr_addr; +wire ram0_wr_en; +wire [ NUM_PARTITIONS -1:0 ] ram0_wr_mask; + +wire [ DATA_WIDTH -1:0 ] ram0_rd_data; +wire [ ADDR_WIDTH -1:0 ] ram0_rd_addr; +wire ram0_rd_en; +wire [ NUM_PARTITIONS -1:0 ] ram0_rd_mask; + +ram_1r1w # ( + .DATA_WIDTH(DATA_WIDTH), + .SIZE(SIZE), + .NUM_PARTITIONS(NUM_PARTITIONS), + .ADDR_WIDTH(ADDR_WIDTH) +) ram0 ( + .clk (clk), + .rst (rst), + + .wr_data (ram0_wr_data), + .wr_addr (ram0_wr_addr), + .wr_en (ram0_wr_en), + .wr_mask (ram0_wr_mask), + + .rd_data (ram0_rd_data), + .rd_addr (ram0_rd_addr), + .rd_en (ram0_rd_en), + .rd_mask (ram0_rd_mask) +); + +wire [ DATA_WIDTH -1:0 ] ram1_wr_data; +wire [ ADDR_WIDTH -1:0 ] ram1_wr_addr; +wire ram1_wr_en; +wire [ NUM_PARTITIONS -1:0 ] ram1_wr_mask; + +wire [ DATA_WIDTH -1:0 ] ram1_rd_data; +wire [ ADDR_WIDTH -1:0 ] ram1_rd_addr; +wire ram1_rd_en; +wire [ NUM_PARTITIONS -1:0 ] ram1_rd_mask; + + +ram_1r1w # ( + .DATA_WIDTH(DATA_WIDTH), + .SIZE(SIZE), + .NUM_PARTITIONS(NUM_PARTITIONS), + .ADDR_WIDTH(ADDR_WIDTH) +) ram1 ( + .clk (clk), + .rst (rst), + + .wr_data (ram1_wr_data), + .wr_addr (ram1_wr_addr), + .wr_en (ram1_wr_en), + .wr_mask (ram1_wr_mask), + + .rd_data (ram1_rd_data), + .rd_addr (ram1_rd_addr), + .rd_en (ram1_rd_en), + .rd_mask (ram1_rd_mask) +); + +RamDemux demux ( + .clk(clk), + .rst(rst), + + .ram_demux__rd_req_r_data(ram_demux__rd_req_r_data), + .ram_demux__rd_req_r_vld(ram_demux__rd_req_r_vld), + .ram_demux__rd_req_r_rdy(ram_demux__rd_req_r_rdy), + + .ram_demux__sel_req_r_data(ram_demux__sel_req_r_data), + .ram_demux__sel_req_r_rdy(ram_demux__sel_req_r_rdy), + .ram_demux__sel_req_r_vld(ram_demux__sel_req_r_vld), + + .ram_demux__sel_resp_s_rdy(ram_demux__sel_resp_s_rdy), + .ram_demux__sel_resp_s_vld(ram_demux__sel_resp_s_vld), + + .ram_demux__wr_req_r_vld(ram_demux__wr_req_r_vld), + .ram_demux__wr_req_r_rdy(ram_demux__wr_req_r_rdy), + .ram_demux__wr_req_r_data(ram_demux__wr_req_r_data), + + .ram_demux__wr_resp_s_rdy(ram_demux__wr_resp_s_rdy), + .ram_demux__wr_resp_s_vld(ram_demux__wr_resp_s_vld), + + .ram_demux__rd_resp_s_rdy(ram_demux__rd_resp_s_rdy), + .ram_demux__rd_resp_s_data(ram_demux__rd_resp_s_data), + .ram_demux__rd_resp_s_vld(ram_demux__rd_resp_s_vld), + + .ram0_rd_data (ram0_rd_data), + .ram0_rd_addr (ram0_rd_addr), + .ram0_rd_mask (ram0_rd_mask), + .ram0_rd_en (ram0_rd_en), + + .ram0_wr_addr (ram0_wr_addr), + .ram0_wr_data (ram0_wr_data), + .ram0_wr_mask (ram0_wr_mask), + .ram0_wr_en (ram0_wr_en), + + .ram1_rd_data (ram1_rd_data), + .ram1_rd_addr (ram1_rd_addr), + .ram1_rd_mask (ram1_rd_mask), + .ram1_rd_en (ram1_rd_en), + + .ram1_wr_addr (ram1_wr_addr), + .ram1_wr_data (ram1_wr_data), + .ram1_wr_mask (ram1_wr_mask), + .ram1_wr_en (ram1_wr_en) +); + +endmodule From 7a5805d9a00509f39d33f176f6eb08ee745bbb57 Mon Sep 17 00:00:00 2001 From: Szymon Gizler Date: Mon, 21 Jul 2025 17:53:10 +0200 Subject: [PATCH 20/30] Document decoder testing --- xls/modules/zstd/README.md | 83 +++++++++++++++++++++++++++++++ xls/modules/zstd/memory/README.md | 41 +++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/xls/modules/zstd/README.md b/xls/modules/zstd/README.md index fb079592e3..aae9a03c8c 100644 --- a/xls/modules/zstd/README.md +++ b/xls/modules/zstd/README.md @@ -452,6 +452,9 @@ results against the decoding of the reference library. Currently, due to the restrictions from the ZSTD frame generator, it is possible to test only the positive cases (decoding valid ZSTD frames). +Verilog tests are written in Python as +[cocotb](https://github.com/cocotb/cocotb) testbench. + ZstdDecoder's main communication interfaces are the AXI buses. Due to the way XLS handles the codegen of DSLX channels that model the AXI channels, the particular ports of the AXI channels are not represented correctly. This @@ -465,6 +468,31 @@ Crossbar](https://github.com/alexforencich/verilog-axi). ![diagram of interfaces of decoder and its wrapper](img/ZSTD_decoder_wrapper.png) +**Figure: Zstd decoder wrapper connection diagram.** + +Cocotb testbench interacts with the decoder with the help of a +[cocotbext-axi](https://github.com/alexforencich/cocotbext-axi) extension that +provides AXI bus models, drivers, monitors and RAM model accessible through AXI +interface. Cocotb AXI Manager is connected to the decoder's `CSR Interface` and +is used to simulate the software's interaction with the decoder. + +The Basic test case for the ZstdDecoder is composed of the following steps: + +1. The testbench generates a ZSTD frame using the + [decodecorpus](https://github.com/facebook/zstd/blob/dev/tests/decodecorpus.c) + utility from the [zstd reference library](https://github.com/facebook/zstd). +2. The encoded frame is placed in an AXI RAM model that is connected to the + decoder's `Memory Interface`. +3. The encoded frame is decoded with the zstd reference library and the results + are represented in the decoder's output format as the expected data from the + simulation. +4. AXI Manager performs a series of writes to the ZstdDecoder CSRs to configure + it and start the decoding process. +5. Testbench waits for the signal on the `Notify` channel and checks the output + of the decoder stored in the memory against the expected output data. +6. Test case succeeds once `Notify` is asserted, all expected data is received + and the decoder lands in `IDLE` state with status `OKAY` in the `Status` CSR. + ### Failure points #### User-facing decoder errors @@ -537,3 +565,58 @@ This is done for example in: * Frame header decoder * SequenceExecutor + +### Testing against [libzstd](https://github.com/facebook/zstd) + +Design is verified by comparing decoding results to the reference library +`libzstd`. ZSTD frames used for testing are generated with +[decodecorpus](https://github.com/facebook/zstd/blob/dev/tests/decodecorpus.c) +utility. The generated frame is then decoded with `libzstd` and with simulated +`ZstdDecoder`. + +#### Positive test cases + +If the results of decoding with `libzstd` are valid, the test runs the same +encoded frame through the simulation of DSLX design. The output of the +simulation is gathered and compared with the results of `libzstd` in terms of +its size and contents. + +Encoded ZSTD frame is generated with the function `GenerateFrame(seed, btype, +output_path)` from +[data_generator](https://github.com/antmicro/xls/blob/main/xls/modules/zstd/cocotb/data_generator.py) +library. This function takes as arguments the seed for the generator, an enum +that codes the type of blocks that should be generated in a given frame and the +output path to write the generated frame into a file. The available block types +are: + +* RAW +* RLE +* COMPRESSED +* RANDOM + +The function returns a vector of bytes representing a valid encoded ZSTD frame. +Such generated frame can be passed to DSLX and cocotb testbenches to be decoded +in the simulation and compared against the results from the reference library. + +Verilog tests are available in the `zstd_dec_cocotb_test.py` file and can be +launched with the following Bazel command: + +```shell +bazel run -c opt -- //xls/modules/zstd:zstd_dec_cocotb_test --logtostderr +``` + +#### Negative test cases + +Currently, `decodecorpus` does not support generating ZSTD frames with subtle +errors that trigger failure points provided in the ZSTD Decoder. Because of +that, it is not possible to efficiently provide valuable negative tests for the +integrated ZSTD Decoder. + +The alternatives for writing negative tests include: + +* Generating a well-known valid ZSTD frame from a specific generator seed and +then tweaking the raw bits in this frame to trigger the error response from the +decoder + +[^1]: `CompressedBlockDecoder` is to be added in follow-up PRs. +[^2]: Checksum verification is currently unsupported. diff --git a/xls/modules/zstd/memory/README.md b/xls/modules/zstd/memory/README.md index 37c20c45a3..ad7d874218 100644 --- a/xls/modules/zstd/memory/README.md +++ b/xls/modules/zstd/memory/README.md @@ -89,3 +89,44 @@ The list below shows the usage of the `MemWriter` proc: 3. Wait for the response submitted on the `resp_s` channel, which indicates if the write operation was successful or an error occurred. + +## Cocotb Simulation + +This directory also contains Verilog simulations of the created modules, +which test their interaction with RAM attached to the AXI bus. These Verilog +simulations provide insight into the design's latency and achievable throughput. + +The simulation interacts with verilog file generated from the particular DSLX +proc through a verilog wrapper. The wrapper is used to create an interface that +is compliant with the AXI specification so that the cocotb testbench can +interact with the DUT with the help of an extension tailored for handling the +AXI bus. + +### Usage + +1. Run the simulation with the following command: + +``` +bazel run -c opt //xls/modules/zstd/memory:_cocotb_test -- --logtostderr +``` + +2. Observe simulation results, e.g. for `mem_writer_cocotb_test`: + +``` +************************************************************************************************************************************************************* +** TEST STATUS SIM TIME (ns) REAL TIME (s) RATIO (ns/s) ** +************************************************************************************************************************************************************* +** mem_writer_cocotb_test.ram_test_single_burst_1_transfer PASS 1970000.00 0.05 40004933.01 ** +** mem_writer_cocotb_test.ram_test_single_burst_2_transfers PASS 2140000.00 0.04 52208013.80 ** +** mem_writer_cocotb_test.ram_test_single_burst_almost_max_burst_transfer PASS 42620000.00 1.00 42734572.11 ** +** mem_writer_cocotb_test.ram_test_single_burst_max_burst_transfer PASS 43380000.00 1.03 42245987.95 ** +** mem_writer_cocotb_test.ram_test_multiburst_2_full_bursts PASS 85940000.00 2.00 42978720.13 ** +** mem_writer_cocotb_test.ram_test_multiburst_1_full_burst_and_single_transfer PASS 44510000.00 1.02 43487911.16 ** +** mem_writer_cocotb_test.ram_test_multiburst_crossing_4kb_boundary PASS 3740000.00 0.06 60190612.91 ** +** mem_writer_cocotb_test.ram_test_multiburst_crossing_4kb_boundary_with_perfectly_aligned_full_bursts PASS 21440000.00 0.50 42469371.00 ** +** mem_writer_cocotb_test.ram_test_multiburst_crossing_4kb_boundary_with_2_full_bursts_and_1_transfer PASS 87070000.00 2.01 43348812.05 ** +** mem_writer_cocotb_test.ram_test_random PASS 4491230000.00 109.05 41184670.96 ** +************************************************************************************************************************************************************* +** TESTS=10 PASS=10 FAIL=0 SKIP=0 4824040000.01 116.82 41296261.92 ** +************************************************************************************************************************************************************* +``` From a058452a1d83a08ba6aec73e5cfeda3ab778bcd2 Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Wed, 23 Apr 2025 22:30:39 +0200 Subject: [PATCH 21/30] dependency_support: Add verilog_axi package Signed-off-by: Robert Winkler --- .../BUILD.bazel | 15 +++++++ .../bundled.BUILD.bazel | 45 +++++++++++++++++++ dependency_support/load_external.bzl | 8 ++++ 3 files changed, 68 insertions(+) create mode 100644 dependency_support/com_github_alexforencich_verilog_axi/BUILD.bazel create mode 100644 dependency_support/com_github_alexforencich_verilog_axi/bundled.BUILD.bazel diff --git a/dependency_support/com_github_alexforencich_verilog_axi/BUILD.bazel b/dependency_support/com_github_alexforencich_verilog_axi/BUILD.bazel new file mode 100644 index 0000000000..4a24c1372f --- /dev/null +++ b/dependency_support/com_github_alexforencich_verilog_axi/BUILD.bazel @@ -0,0 +1,15 @@ +# Copyright 2025 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Needed to make this a package. diff --git a/dependency_support/com_github_alexforencich_verilog_axi/bundled.BUILD.bazel b/dependency_support/com_github_alexforencich_verilog_axi/bundled.BUILD.bazel new file mode 100644 index 0000000000..296e2bc0f6 --- /dev/null +++ b/dependency_support/com_github_alexforencich_verilog_axi/bundled.BUILD.bazel @@ -0,0 +1,45 @@ +# Copyright 2025 The XLS Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@xls_pip_deps//:requirements.bzl", "requirement") + +package(default_visibility = ["//visibility:public"]) + +exports_files( + glob(["rtl/*.v"]), +) + +py_binary( + name = "axi_crossbar_wrap", + srcs = ["rtl/axi_crossbar_wrap.py"], + deps = [requirement("Jinja2")], +) + +py_binary( + name = "axi_interconnect_wrap", + srcs = ["rtl/axi_interconnect_wrap.py"], + deps = [requirement("Jinja2")], +) + +py_binary( + name = "axil_crossbar_wrap", + srcs = ["rtl/axi_crossbar_wrap.py"], + deps = [requirement("Jinja2")], +) + +py_binary( + name = "axil_interconnect_wrap", + srcs = ["rtl/axil_interconnect_wrap.py"], + deps = [requirement("Jinja2")], +) diff --git a/dependency_support/load_external.bzl b/dependency_support/load_external.bzl index 73b6b7b9f0..aefbe77113 100644 --- a/dependency_support/load_external.bzl +++ b/dependency_support/load_external.bzl @@ -90,3 +90,11 @@ def load_external_repositories(): urls = ["https://github.com/facebook/zstd/archive/fdfb2aff39dc498372d8c9e5f2330b692fea9794.zip"], build_file = Label("//dependency_support/com_github_facebook_zstd:bundled.BUILD.bazel"), ) + + http_archive( + name = "com_github_alexforencich_verilog_axi", + sha256 = "f3b58406b51950584cc7b0c67b0710cef10cb14e1f5576e97a2f0b1c0b12fcbe", + strip_prefix = "verilog-axi-516bd5dadc3365b7f9e225d2af8fe0b8d804fe53", + urls = ["https://github.com/alexforencich/verilog-axi/archive/516bd5dadc3365b7f9e225d2af8fe0b8d804fe53.zip"], + build_file = "//dependency_support/com_github_alexforencich_verilog_axi:bundled.BUILD.bazel", + ) From d092144c66355dd7351d33f25e6e64617000890a Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Wed, 23 Jul 2025 15:07:45 +0200 Subject: [PATCH 22/30] Use bazel package with verilog_axi Signed-off-by: Robert Winkler --- xls/modules/zstd/BUILD | 29 +- xls/modules/zstd/external/BUILD | 48 - xls/modules/zstd/external/LICENSE | 19 - xls/modules/zstd/external/arbiter.v | 159 --- xls/modules/zstd/external/axi_crossbar.v | 391 ------ xls/modules/zstd/external/axi_crossbar_addr.v | 418 ------ xls/modules/zstd/external/axi_crossbar_rd.v | 569 -------- xls/modules/zstd/external/axi_crossbar_wr.v | 678 --------- .../zstd/external/axi_crossbar_wrapper.v | 1246 ----------------- xls/modules/zstd/external/axi_register_rd.v | 530 ------- xls/modules/zstd/external/axi_register_wr.v | 691 --------- xls/modules/zstd/external/priority_encoder.v | 92 -- xls/modules/zstd/zstd_dec_cocotb_test.py | 18 +- 13 files changed, 28 insertions(+), 4860 deletions(-) delete mode 100644 xls/modules/zstd/external/BUILD delete mode 100644 xls/modules/zstd/external/LICENSE delete mode 100644 xls/modules/zstd/external/arbiter.v delete mode 100644 xls/modules/zstd/external/axi_crossbar.v delete mode 100644 xls/modules/zstd/external/axi_crossbar_addr.v delete mode 100644 xls/modules/zstd/external/axi_crossbar_rd.v delete mode 100644 xls/modules/zstd/external/axi_crossbar_wr.v delete mode 100644 xls/modules/zstd/external/axi_crossbar_wrapper.v delete mode 100644 xls/modules/zstd/external/axi_register_rd.v delete mode 100644 xls/modules/zstd/external/axi_register_wr.v delete mode 100644 xls/modules/zstd/external/priority_encoder.v diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 82449a54ba..eb4e7cf9a6 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -1785,6 +1785,15 @@ filegroup( ], ) +genrule( + name = "axi_crossbar_wrapper", + outs = ["axi_crossbar_wrapper.v"], + cmd = "$(location @com_github_alexforencich_verilog_axi//:axi_crossbar_wrap) -p 15 1 -n axi_crossbar_wrapper -o $(OUTS)", + tools = [ + "@com_github_alexforencich_verilog_axi//:axi_crossbar_wrap", + ], +) + py_test( name = "zstd_dec_cocotb_test", srcs = ["zstd_dec_cocotb_test.py"], @@ -1828,20 +1837,20 @@ py_test( "data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400025.zst", "data/treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400061.zst", "data/treeless_huffman_literals_rle_sequences_seed_403927.zst", + ":axi_crossbar_wrapper.v", ":zstd_dec.v", - "//xls/modules/zstd:zstd_dec_xx_fse_default", - "//xls/modules/zstd/external:arbiter.v", - "//xls/modules/zstd/external:axi_crossbar.v", - "//xls/modules/zstd/external:axi_crossbar_addr.v", - "//xls/modules/zstd/external:axi_crossbar_rd.v", - "//xls/modules/zstd/external:axi_crossbar_wr.v", - "//xls/modules/zstd/external:axi_crossbar_wrapper.v", - "//xls/modules/zstd/external:axi_register_rd.v", - "//xls/modules/zstd/external:axi_register_wr.v", - "//xls/modules/zstd/external:priority_encoder.v", + ":zstd_dec_xx_fse_default", "//xls/modules/zstd/rtl:ram_1r1w.v", "//xls/modules/zstd/rtl:xls_fifo_wrapper.sv", "//xls/modules/zstd/rtl:zstd_dec_wrapper.sv", + "@com_github_alexforencich_verilog_axi//:rtl/arbiter.v", + "@com_github_alexforencich_verilog_axi//:rtl/axi_crossbar.v", + "@com_github_alexforencich_verilog_axi//:rtl/axi_crossbar_addr.v", + "@com_github_alexforencich_verilog_axi//:rtl/axi_crossbar_rd.v", + "@com_github_alexforencich_verilog_axi//:rtl/axi_crossbar_wr.v", + "@com_github_alexforencich_verilog_axi//:rtl/axi_register_rd.v", + "@com_github_alexforencich_verilog_axi//:rtl/axi_register_wr.v", + "@com_github_alexforencich_verilog_axi//:rtl/priority_encoder.v", "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], diff --git a/xls/modules/zstd/external/BUILD b/xls/modules/zstd/external/BUILD deleted file mode 100644 index f0e3c97626..0000000000 --- a/xls/modules/zstd/external/BUILD +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2024 The XLS Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Collection of external RTL sources - -This package exports external verilog sources required by the ZSTD Decoder -in the verilog tests. - -The exported files come from the Open Source library of the AXI4 and AXI4 lite -bus components released under MIT license. - -The sources contain an implementation of the AXI4 crossbar which is used in the -verilog tests of the ZSTD Decoder to connect multiple AXI interfaces into a single -AXI interface that forms the IO of the ZSTD Decoder verilog wrapper used in the tests. - -Source: https://github.com/alexforencich/verilog-axi -""" - -package( - default_applicable_licenses = ["//:license"], - default_visibility = ["//xls:xls_users"], - licenses = ["notice"], -) - -exports_files( - [ - "arbiter.v", - "axi_crossbar.v", - "axi_crossbar_addr.v", - "axi_crossbar_rd.v", - "axi_crossbar_wr.v", - "axi_crossbar_wrapper.v", - "axi_register_rd.v", - "axi_register_wr.v", - "priority_encoder.v", - ], -) diff --git a/xls/modules/zstd/external/LICENSE b/xls/modules/zstd/external/LICENSE deleted file mode 100644 index 6923387c75..0000000000 --- a/xls/modules/zstd/external/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018 Alex Forencich - -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/xls/modules/zstd/external/arbiter.v b/xls/modules/zstd/external/arbiter.v deleted file mode 100644 index cfac70d1c6..0000000000 --- a/xls/modules/zstd/external/arbiter.v +++ /dev/null @@ -1,159 +0,0 @@ -/* - -Copyright (c) 2014-2021 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * Arbiter module - */ -module arbiter # -( - parameter PORTS = 4, - // select round robin arbitration - parameter ARB_TYPE_ROUND_ROBIN = 0, - // blocking arbiter enable - parameter ARB_BLOCK = 0, - // block on acknowledge assert when nonzero, request deassert when 0 - parameter ARB_BLOCK_ACK = 1, - // LSB priority selection - parameter ARB_LSB_HIGH_PRIORITY = 0 -) -( - input wire clk, - input wire rst, - - input wire [PORTS-1:0] request, - input wire [PORTS-1:0] acknowledge, - - output wire [PORTS-1:0] grant, - output wire grant_valid, - output wire [$clog2(PORTS)-1:0] grant_encoded -); - -reg [PORTS-1:0] grant_reg = 0, grant_next; -reg grant_valid_reg = 0, grant_valid_next; -reg [$clog2(PORTS)-1:0] grant_encoded_reg = 0, grant_encoded_next; - -assign grant_valid = grant_valid_reg; -assign grant = grant_reg; -assign grant_encoded = grant_encoded_reg; - -wire request_valid; -wire [$clog2(PORTS)-1:0] request_index; -wire [PORTS-1:0] request_mask; - -priority_encoder #( - .WIDTH(PORTS), - .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) -) -priority_encoder_inst ( - .input_unencoded(request), - .output_valid(request_valid), - .output_encoded(request_index), - .output_unencoded(request_mask) -); - -reg [PORTS-1:0] mask_reg = 0, mask_next; - -wire masked_request_valid; -wire [$clog2(PORTS)-1:0] masked_request_index; -wire [PORTS-1:0] masked_request_mask; - -priority_encoder #( - .WIDTH(PORTS), - .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) -) -priority_encoder_masked ( - .input_unencoded(request & mask_reg), - .output_valid(masked_request_valid), - .output_encoded(masked_request_index), - .output_unencoded(masked_request_mask) -); - -always @* begin - grant_next = 0; - grant_valid_next = 0; - grant_encoded_next = 0; - mask_next = mask_reg; - - if (ARB_BLOCK && !ARB_BLOCK_ACK && grant_reg & request) begin - // granted request still asserted; hold it - grant_valid_next = grant_valid_reg; - grant_next = grant_reg; - grant_encoded_next = grant_encoded_reg; - end else if (ARB_BLOCK && ARB_BLOCK_ACK && grant_valid && !(grant_reg & acknowledge)) begin - // granted request not yet acknowledged; hold it - grant_valid_next = grant_valid_reg; - grant_next = grant_reg; - grant_encoded_next = grant_encoded_reg; - end else if (request_valid) begin - if (ARB_TYPE_ROUND_ROBIN) begin - if (masked_request_valid) begin - grant_valid_next = 1; - grant_next = masked_request_mask; - grant_encoded_next = masked_request_index; - if (ARB_LSB_HIGH_PRIORITY) begin - mask_next = {PORTS{1'b1}} << (masked_request_index + 1); - end else begin - mask_next = {PORTS{1'b1}} >> (PORTS - masked_request_index); - end - end else begin - grant_valid_next = 1; - grant_next = request_mask; - grant_encoded_next = request_index; - if (ARB_LSB_HIGH_PRIORITY) begin - mask_next = {PORTS{1'b1}} << (request_index + 1); - end else begin - mask_next = {PORTS{1'b1}} >> (PORTS - request_index); - end - end - end else begin - grant_valid_next = 1; - grant_next = request_mask; - grant_encoded_next = request_index; - end - end -end - -always @(posedge clk) begin - if (rst) begin - grant_reg <= 0; - grant_valid_reg <= 0; - grant_encoded_reg <= 0; - mask_reg <= 0; - end else begin - grant_reg <= grant_next; - grant_valid_reg <= grant_valid_next; - grant_encoded_reg <= grant_encoded_next; - mask_reg <= mask_next; - end -end - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_crossbar.v b/xls/modules/zstd/external/axi_crossbar.v deleted file mode 100644 index 991d45403a..0000000000 --- a/xls/modules/zstd/external/axi_crossbar.v +++ /dev/null @@ -1,391 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 crossbar - */ -module axi_crossbar # -( - // Number of AXI inputs (slave interfaces) - parameter S_COUNT = 4, - // Number of AXI outputs (master interfaces) - parameter M_COUNT = 4, - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Input ID field width (from AXI masters) - parameter S_ID_WIDTH = 8, - // Output ID field width (towards AXI slaves) - // Additional bits required for response routing - parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), - // Propagate awuser signal - parameter AWUSER_ENABLE = 0, - // Width of awuser signal - parameter AWUSER_WIDTH = 1, - // Propagate wuser signal - parameter WUSER_ENABLE = 0, - // Width of wuser signal - parameter WUSER_WIDTH = 1, - // Propagate buser signal - parameter BUSER_ENABLE = 0, - // Width of buser signal - parameter BUSER_WIDTH = 1, - // Propagate aruser signal - parameter ARUSER_ENABLE = 0, - // Width of aruser signal - parameter ARUSER_WIDTH = 1, - // Propagate ruser signal - parameter RUSER_ENABLE = 0, - // Width of ruser signal - parameter RUSER_WIDTH = 1, - // Number of concurrent unique IDs for each slave interface - // S_COUNT concatenated fields of 32 bits - parameter S_THREADS = {S_COUNT{32'd2}}, - // Number of concurrent operations for each slave interface - // S_COUNT concatenated fields of 32 bits - parameter S_ACCEPT = {S_COUNT{32'd16}}, - // Number of regions per master interface - parameter M_REGIONS = 1, - // Master interface base addresses - // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits - // set to zero for default addressing based on M_ADDR_WIDTH - parameter M_BASE_ADDR = 0, - // Master interface address widths - // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits - parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, - // Read connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}}, - // Write connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}}, - // Number of concurrent operations for each master interface - // M_COUNT concatenated fields of 32 bits - parameter M_ISSUE = {M_COUNT{32'd4}}, - // Secure master (fail operations based on awprot/arprot) - // M_COUNT bits - parameter M_SECURE = {M_COUNT{1'b0}}, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_AW_REG_TYPE = {S_COUNT{2'd0}}, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_W_REG_TYPE = {S_COUNT{2'd0}}, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_B_REG_TYPE = {S_COUNT{2'd1}}, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_AR_REG_TYPE = {S_COUNT{2'd0}}, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_R_REG_TYPE = {S_COUNT{2'd2}}, - // Master interface AW channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_AW_REG_TYPE = {M_COUNT{2'd1}}, - // Master interface W channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_W_REG_TYPE = {M_COUNT{2'd2}}, - // Master interface B channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_B_REG_TYPE = {M_COUNT{2'd0}}, - // Master interface AR channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_AR_REG_TYPE = {M_COUNT{2'd1}}, - // Master interface R channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_R_REG_TYPE = {M_COUNT{2'd0}} -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interfaces - */ - input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid, - input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr, - input wire [S_COUNT*8-1:0] s_axi_awlen, - input wire [S_COUNT*3-1:0] s_axi_awsize, - input wire [S_COUNT*2-1:0] s_axi_awburst, - input wire [S_COUNT-1:0] s_axi_awlock, - input wire [S_COUNT*4-1:0] s_axi_awcache, - input wire [S_COUNT*3-1:0] s_axi_awprot, - input wire [S_COUNT*4-1:0] s_axi_awqos, - input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser, - input wire [S_COUNT-1:0] s_axi_awvalid, - output wire [S_COUNT-1:0] s_axi_awready, - input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata, - input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb, - input wire [S_COUNT-1:0] s_axi_wlast, - input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser, - input wire [S_COUNT-1:0] s_axi_wvalid, - output wire [S_COUNT-1:0] s_axi_wready, - output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid, - output wire [S_COUNT*2-1:0] s_axi_bresp, - output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser, - output wire [S_COUNT-1:0] s_axi_bvalid, - input wire [S_COUNT-1:0] s_axi_bready, - input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid, - input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr, - input wire [S_COUNT*8-1:0] s_axi_arlen, - input wire [S_COUNT*3-1:0] s_axi_arsize, - input wire [S_COUNT*2-1:0] s_axi_arburst, - input wire [S_COUNT-1:0] s_axi_arlock, - input wire [S_COUNT*4-1:0] s_axi_arcache, - input wire [S_COUNT*3-1:0] s_axi_arprot, - input wire [S_COUNT*4-1:0] s_axi_arqos, - input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser, - input wire [S_COUNT-1:0] s_axi_arvalid, - output wire [S_COUNT-1:0] s_axi_arready, - output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid, - output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata, - output wire [S_COUNT*2-1:0] s_axi_rresp, - output wire [S_COUNT-1:0] s_axi_rlast, - output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser, - output wire [S_COUNT-1:0] s_axi_rvalid, - input wire [S_COUNT-1:0] s_axi_rready, - - /* - * AXI master interfaces - */ - output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid, - output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr, - output wire [M_COUNT*8-1:0] m_axi_awlen, - output wire [M_COUNT*3-1:0] m_axi_awsize, - output wire [M_COUNT*2-1:0] m_axi_awburst, - output wire [M_COUNT-1:0] m_axi_awlock, - output wire [M_COUNT*4-1:0] m_axi_awcache, - output wire [M_COUNT*3-1:0] m_axi_awprot, - output wire [M_COUNT*4-1:0] m_axi_awqos, - output wire [M_COUNT*4-1:0] m_axi_awregion, - output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser, - output wire [M_COUNT-1:0] m_axi_awvalid, - input wire [M_COUNT-1:0] m_axi_awready, - output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata, - output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb, - output wire [M_COUNT-1:0] m_axi_wlast, - output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser, - output wire [M_COUNT-1:0] m_axi_wvalid, - input wire [M_COUNT-1:0] m_axi_wready, - input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid, - input wire [M_COUNT*2-1:0] m_axi_bresp, - input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser, - input wire [M_COUNT-1:0] m_axi_bvalid, - output wire [M_COUNT-1:0] m_axi_bready, - output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid, - output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr, - output wire [M_COUNT*8-1:0] m_axi_arlen, - output wire [M_COUNT*3-1:0] m_axi_arsize, - output wire [M_COUNT*2-1:0] m_axi_arburst, - output wire [M_COUNT-1:0] m_axi_arlock, - output wire [M_COUNT*4-1:0] m_axi_arcache, - output wire [M_COUNT*3-1:0] m_axi_arprot, - output wire [M_COUNT*4-1:0] m_axi_arqos, - output wire [M_COUNT*4-1:0] m_axi_arregion, - output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser, - output wire [M_COUNT-1:0] m_axi_arvalid, - input wire [M_COUNT-1:0] m_axi_arready, - input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid, - input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata, - input wire [M_COUNT*2-1:0] m_axi_rresp, - input wire [M_COUNT-1:0] m_axi_rlast, - input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser, - input wire [M_COUNT-1:0] m_axi_rvalid, - output wire [M_COUNT-1:0] m_axi_rready -); - -axi_crossbar_wr #( - .S_COUNT(S_COUNT), - .M_COUNT(M_COUNT), - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .S_ID_WIDTH(S_ID_WIDTH), - .M_ID_WIDTH(M_ID_WIDTH), - .AWUSER_ENABLE(AWUSER_ENABLE), - .AWUSER_WIDTH(AWUSER_WIDTH), - .WUSER_ENABLE(WUSER_ENABLE), - .WUSER_WIDTH(WUSER_WIDTH), - .BUSER_ENABLE(BUSER_ENABLE), - .BUSER_WIDTH(BUSER_WIDTH), - .S_THREADS(S_THREADS), - .S_ACCEPT(S_ACCEPT), - .M_REGIONS(M_REGIONS), - .M_BASE_ADDR(M_BASE_ADDR), - .M_ADDR_WIDTH(M_ADDR_WIDTH), - .M_CONNECT(M_CONNECT_WRITE), - .M_ISSUE(M_ISSUE), - .M_SECURE(M_SECURE), - .S_AW_REG_TYPE(S_AW_REG_TYPE), - .S_W_REG_TYPE (S_W_REG_TYPE), - .S_B_REG_TYPE (S_B_REG_TYPE) -) -axi_crossbar_wr_inst ( - .clk(clk), - .rst(rst), - - /* - * AXI slave interfaces - */ - .s_axi_awid(s_axi_awid), - .s_axi_awaddr(s_axi_awaddr), - .s_axi_awlen(s_axi_awlen), - .s_axi_awsize(s_axi_awsize), - .s_axi_awburst(s_axi_awburst), - .s_axi_awlock(s_axi_awlock), - .s_axi_awcache(s_axi_awcache), - .s_axi_awprot(s_axi_awprot), - .s_axi_awqos(s_axi_awqos), - .s_axi_awuser(s_axi_awuser), - .s_axi_awvalid(s_axi_awvalid), - .s_axi_awready(s_axi_awready), - .s_axi_wdata(s_axi_wdata), - .s_axi_wstrb(s_axi_wstrb), - .s_axi_wlast(s_axi_wlast), - .s_axi_wuser(s_axi_wuser), - .s_axi_wvalid(s_axi_wvalid), - .s_axi_wready(s_axi_wready), - .s_axi_bid(s_axi_bid), - .s_axi_bresp(s_axi_bresp), - .s_axi_buser(s_axi_buser), - .s_axi_bvalid(s_axi_bvalid), - .s_axi_bready(s_axi_bready), - - /* - * AXI master interfaces - */ - .m_axi_awid(m_axi_awid), - .m_axi_awaddr(m_axi_awaddr), - .m_axi_awlen(m_axi_awlen), - .m_axi_awsize(m_axi_awsize), - .m_axi_awburst(m_axi_awburst), - .m_axi_awlock(m_axi_awlock), - .m_axi_awcache(m_axi_awcache), - .m_axi_awprot(m_axi_awprot), - .m_axi_awqos(m_axi_awqos), - .m_axi_awregion(m_axi_awregion), - .m_axi_awuser(m_axi_awuser), - .m_axi_awvalid(m_axi_awvalid), - .m_axi_awready(m_axi_awready), - .m_axi_wdata(m_axi_wdata), - .m_axi_wstrb(m_axi_wstrb), - .m_axi_wlast(m_axi_wlast), - .m_axi_wuser(m_axi_wuser), - .m_axi_wvalid(m_axi_wvalid), - .m_axi_wready(m_axi_wready), - .m_axi_bid(m_axi_bid), - .m_axi_bresp(m_axi_bresp), - .m_axi_buser(m_axi_buser), - .m_axi_bvalid(m_axi_bvalid), - .m_axi_bready(m_axi_bready) -); - -axi_crossbar_rd #( - .S_COUNT(S_COUNT), - .M_COUNT(M_COUNT), - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .S_ID_WIDTH(S_ID_WIDTH), - .M_ID_WIDTH(M_ID_WIDTH), - .ARUSER_ENABLE(ARUSER_ENABLE), - .ARUSER_WIDTH(ARUSER_WIDTH), - .RUSER_ENABLE(RUSER_ENABLE), - .RUSER_WIDTH(RUSER_WIDTH), - .S_THREADS(S_THREADS), - .S_ACCEPT(S_ACCEPT), - .M_REGIONS(M_REGIONS), - .M_BASE_ADDR(M_BASE_ADDR), - .M_ADDR_WIDTH(M_ADDR_WIDTH), - .M_CONNECT(M_CONNECT_READ), - .M_ISSUE(M_ISSUE), - .M_SECURE(M_SECURE), - .S_AR_REG_TYPE(S_AR_REG_TYPE), - .S_R_REG_TYPE (S_R_REG_TYPE) -) -axi_crossbar_rd_inst ( - .clk(clk), - .rst(rst), - - /* - * AXI slave interfaces - */ - .s_axi_arid(s_axi_arid), - .s_axi_araddr(s_axi_araddr), - .s_axi_arlen(s_axi_arlen), - .s_axi_arsize(s_axi_arsize), - .s_axi_arburst(s_axi_arburst), - .s_axi_arlock(s_axi_arlock), - .s_axi_arcache(s_axi_arcache), - .s_axi_arprot(s_axi_arprot), - .s_axi_arqos(s_axi_arqos), - .s_axi_aruser(s_axi_aruser), - .s_axi_arvalid(s_axi_arvalid), - .s_axi_arready(s_axi_arready), - .s_axi_rid(s_axi_rid), - .s_axi_rdata(s_axi_rdata), - .s_axi_rresp(s_axi_rresp), - .s_axi_rlast(s_axi_rlast), - .s_axi_ruser(s_axi_ruser), - .s_axi_rvalid(s_axi_rvalid), - .s_axi_rready(s_axi_rready), - - /* - * AXI master interfaces - */ - .m_axi_arid(m_axi_arid), - .m_axi_araddr(m_axi_araddr), - .m_axi_arlen(m_axi_arlen), - .m_axi_arsize(m_axi_arsize), - .m_axi_arburst(m_axi_arburst), - .m_axi_arlock(m_axi_arlock), - .m_axi_arcache(m_axi_arcache), - .m_axi_arprot(m_axi_arprot), - .m_axi_arqos(m_axi_arqos), - .m_axi_arregion(m_axi_arregion), - .m_axi_aruser(m_axi_aruser), - .m_axi_arvalid(m_axi_arvalid), - .m_axi_arready(m_axi_arready), - .m_axi_rid(m_axi_rid), - .m_axi_rdata(m_axi_rdata), - .m_axi_rresp(m_axi_rresp), - .m_axi_rlast(m_axi_rlast), - .m_axi_ruser(m_axi_ruser), - .m_axi_rvalid(m_axi_rvalid), - .m_axi_rready(m_axi_rready) -); - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_addr.v b/xls/modules/zstd/external/axi_crossbar_addr.v deleted file mode 100644 index 7b7846526b..0000000000 --- a/xls/modules/zstd/external/axi_crossbar_addr.v +++ /dev/null @@ -1,418 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 crossbar address decode and admission control - */ -module axi_crossbar_addr # -( - // Slave interface index - parameter S = 0, - // Number of AXI inputs (slave interfaces) - parameter S_COUNT = 4, - // Number of AXI outputs (master interfaces) - parameter M_COUNT = 4, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // ID field width - parameter ID_WIDTH = 8, - // Number of concurrent unique IDs - parameter S_THREADS = 32'd2, - // Number of concurrent operations - parameter S_ACCEPT = 32'd16, - // Number of regions per master interface - parameter M_REGIONS = 1, - // Master interface base addresses - // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits - // set to zero for default addressing based on M_ADDR_WIDTH - parameter M_BASE_ADDR = 0, - // Master interface address widths - // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits - parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, - // Connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}}, - // Secure master (fail operations based on awprot/arprot) - // M_COUNT bits - parameter M_SECURE = {M_COUNT{1'b0}}, - // Enable write command output - parameter WC_OUTPUT = 0 -) -( - input wire clk, - input wire rst, - - /* - * Address input - */ - input wire [ID_WIDTH-1:0] s_axi_aid, - input wire [ADDR_WIDTH-1:0] s_axi_aaddr, - input wire [2:0] s_axi_aprot, - input wire [3:0] s_axi_aqos, - input wire s_axi_avalid, - output wire s_axi_aready, - - /* - * Address output - */ - output wire [3:0] m_axi_aregion, - output wire [$clog2(M_COUNT)-1:0] m_select, - output wire m_axi_avalid, - input wire m_axi_aready, - - /* - * Write command output - */ - output wire [$clog2(M_COUNT)-1:0] m_wc_select, - output wire m_wc_decerr, - output wire m_wc_valid, - input wire m_wc_ready, - - /* - * Reply command output - */ - output wire m_rc_decerr, - output wire m_rc_valid, - input wire m_rc_ready, - - /* - * Completion input - */ - input wire [ID_WIDTH-1:0] s_cpl_id, - input wire s_cpl_valid -); - -parameter CL_S_COUNT = $clog2(S_COUNT); -parameter CL_M_COUNT = $clog2(M_COUNT); - -parameter S_INT_THREADS = S_THREADS > S_ACCEPT ? S_ACCEPT : S_THREADS; -parameter CL_S_INT_THREADS = $clog2(S_INT_THREADS); -parameter CL_S_ACCEPT = $clog2(S_ACCEPT); - -// default address computation -function [M_COUNT*M_REGIONS*ADDR_WIDTH-1:0] calcBaseAddrs(input [31:0] dummy); - integer i; - reg [ADDR_WIDTH-1:0] base; - reg [ADDR_WIDTH-1:0] width; - reg [ADDR_WIDTH-1:0] size; - reg [ADDR_WIDTH-1:0] mask; - begin - calcBaseAddrs = {M_COUNT*M_REGIONS*ADDR_WIDTH{1'b0}}; - base = 0; - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - width = M_ADDR_WIDTH[i*32 +: 32]; - mask = {ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - width); - size = mask + 1; - if (width > 0) begin - if ((base & mask) != 0) begin - base = base + size - (base & mask); // align - end - calcBaseAddrs[i * ADDR_WIDTH +: ADDR_WIDTH] = base; - base = base + size; // increment - end - end - end -endfunction - -parameter M_BASE_ADDR_INT = M_BASE_ADDR ? M_BASE_ADDR : calcBaseAddrs(0); - -integer i, j; - -// check configuration -initial begin - if (S_ACCEPT < 1) begin - $error("Error: need at least 1 accept (instance %m)"); - $finish; - end - - if (S_THREADS < 1) begin - $error("Error: need at least 1 thread (instance %m)"); - $finish; - end - - if (S_THREADS > S_ACCEPT) begin - $warning("Warning: requested thread count larger than accept count; limiting thread count to accept count (instance %m)"); - end - - if (M_REGIONS < 1) begin - $error("Error: need at least 1 region (instance %m)"); - $finish; - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin - $error("Error: address width out of range (instance %m)"); - $finish; - end - end - - $display("Addressing configuration for axi_crossbar_addr instance %m"); - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32]) begin - $display("%2d (%2d): %x / %02d -- %x-%x", - i/M_REGIONS, i%M_REGIONS, - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[i*32 +: 32], - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) - ); - end - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if ((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & (2**M_ADDR_WIDTH[i*32 +: 32]-1)) != 0) begin - $display("Region not aligned:"); - $display("%2d (%2d): %x / %2d -- %x-%x", - i/M_REGIONS, i%M_REGIONS, - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[i*32 +: 32], - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) - ); - $error("Error: address range not aligned (instance %m)"); - $finish; - end - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - for (j = i+1; j < M_COUNT*M_REGIONS; j = j + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32] && M_ADDR_WIDTH[j*32 +: 32]) begin - if (((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])))) - && ((M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin - $display("Overlapping regions:"); - $display("%2d (%2d): %x / %2d -- %x-%x", - i/M_REGIONS, i%M_REGIONS, - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[i*32 +: 32], - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), - M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) - ); - $display("%2d (%2d): %x / %2d -- %x-%x", - j/M_REGIONS, j%M_REGIONS, - M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH], - M_ADDR_WIDTH[j*32 +: 32], - M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]), - M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])) - ); - $error("Error: address ranges overlap (instance %m)"); - $finish; - end - end - end - end -end - -localparam [2:0] - STATE_IDLE = 3'd0, - STATE_DECODE = 3'd1; - -reg [2:0] state_reg = STATE_IDLE, state_next; - -reg s_axi_aready_reg = 0, s_axi_aready_next; - -reg [3:0] m_axi_aregion_reg = 4'd0, m_axi_aregion_next; -reg [CL_M_COUNT-1:0] m_select_reg = 0, m_select_next; -reg m_axi_avalid_reg = 1'b0, m_axi_avalid_next; -reg m_decerr_reg = 1'b0, m_decerr_next; -reg m_wc_valid_reg = 1'b0, m_wc_valid_next; -reg m_rc_valid_reg = 1'b0, m_rc_valid_next; - -assign s_axi_aready = s_axi_aready_reg; - -assign m_axi_aregion = m_axi_aregion_reg; -assign m_select = m_select_reg; -assign m_axi_avalid = m_axi_avalid_reg; - -assign m_wc_select = m_select_reg; -assign m_wc_decerr = m_decerr_reg; -assign m_wc_valid = m_wc_valid_reg; - -assign m_rc_decerr = m_decerr_reg; -assign m_rc_valid = m_rc_valid_reg; - -reg match; -reg trans_start; -reg trans_complete; - -reg [$clog2(S_ACCEPT+1)-1:0] trans_count_reg = 0; -wire trans_limit = trans_count_reg >= S_ACCEPT && !trans_complete; - -// transfer ID thread tracking -reg [ID_WIDTH-1:0] thread_id_reg[S_INT_THREADS-1:0]; -reg [CL_M_COUNT-1:0] thread_m_reg[S_INT_THREADS-1:0]; -reg [3:0] thread_region_reg[S_INT_THREADS-1:0]; -reg [$clog2(S_ACCEPT+1)-1:0] thread_count_reg[S_INT_THREADS-1:0]; - -wire [S_INT_THREADS-1:0] thread_active; -wire [S_INT_THREADS-1:0] thread_match; -wire [S_INT_THREADS-1:0] thread_match_dest; -wire [S_INT_THREADS-1:0] thread_cpl_match; -wire [S_INT_THREADS-1:0] thread_trans_start; -wire [S_INT_THREADS-1:0] thread_trans_complete; - -generate - genvar n; - - for (n = 0; n < S_INT_THREADS; n = n + 1) begin - initial begin - thread_count_reg[n] <= 0; - end - - assign thread_active[n] = thread_count_reg[n] != 0; - assign thread_match[n] = thread_active[n] && thread_id_reg[n] == s_axi_aid; - assign thread_match_dest[n] = thread_match[n] && thread_m_reg[n] == m_select_next && (M_REGIONS < 2 || thread_region_reg[n] == m_axi_aregion_next); - assign thread_cpl_match[n] = thread_active[n] && thread_id_reg[n] == s_cpl_id; - assign thread_trans_start[n] = (thread_match[n] || (!thread_active[n] && !thread_match && !(thread_trans_start & ({S_INT_THREADS{1'b1}} >> (S_INT_THREADS-n))))) && trans_start; - assign thread_trans_complete[n] = thread_cpl_match[n] && trans_complete; - - always @(posedge clk) begin - if (rst) begin - thread_count_reg[n] <= 0; - end else begin - if (thread_trans_start[n] && !thread_trans_complete[n]) begin - thread_count_reg[n] <= thread_count_reg[n] + 1; - end else if (!thread_trans_start[n] && thread_trans_complete[n]) begin - thread_count_reg[n] <= thread_count_reg[n] - 1; - end - end - - if (thread_trans_start[n]) begin - thread_id_reg[n] <= s_axi_aid; - thread_m_reg[n] <= m_select_next; - thread_region_reg[n] <= m_axi_aregion_next; - end - end - end -endgenerate - -always @* begin - state_next = STATE_IDLE; - - match = 1'b0; - trans_start = 1'b0; - trans_complete = 1'b0; - - s_axi_aready_next = 1'b0; - - m_axi_aregion_next = m_axi_aregion_reg; - m_select_next = m_select_reg; - m_axi_avalid_next = m_axi_avalid_reg && !m_axi_aready; - m_decerr_next = m_decerr_reg; - m_wc_valid_next = m_wc_valid_reg && !m_wc_ready; - m_rc_valid_next = m_rc_valid_reg && !m_rc_ready; - - case (state_reg) - STATE_IDLE: begin - // idle state, store values - s_axi_aready_next = 1'b0; - - if (s_axi_avalid && !s_axi_aready) begin - match = 1'b0; - for (i = 0; i < M_COUNT; i = i + 1) begin - for (j = 0; j < M_REGIONS; j = j + 1) begin - if (M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32] && (!M_SECURE[i] || !s_axi_aprot[1]) && (M_CONNECT & (1 << (S+i*S_COUNT))) && (s_axi_aaddr >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32]) == (M_BASE_ADDR_INT[(i*M_REGIONS+j)*ADDR_WIDTH +: ADDR_WIDTH] >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32])) begin - m_select_next = i; - m_axi_aregion_next = j; - match = 1'b1; - end - end - end - - if (match) begin - // address decode successful - if (!trans_limit && (thread_match_dest || (!(&thread_active) && !thread_match))) begin - // transaction limit not reached - m_axi_avalid_next = 1'b1; - m_decerr_next = 1'b0; - m_wc_valid_next = WC_OUTPUT; - m_rc_valid_next = 1'b0; - trans_start = 1'b1; - state_next = STATE_DECODE; - end else begin - // transaction limit reached; block in idle - state_next = STATE_IDLE; - end - end else begin - // decode error - m_axi_avalid_next = 1'b0; - m_decerr_next = 1'b1; - m_wc_valid_next = WC_OUTPUT; - m_rc_valid_next = 1'b1; - state_next = STATE_DECODE; - end - end else begin - state_next = STATE_IDLE; - end - end - STATE_DECODE: begin - if (!m_axi_avalid_next && (!m_wc_valid_next || !WC_OUTPUT) && !m_rc_valid_next) begin - s_axi_aready_next = 1'b1; - state_next = STATE_IDLE; - end else begin - state_next = STATE_DECODE; - end - end - endcase - - // manage completions - trans_complete = s_cpl_valid; -end - -always @(posedge clk) begin - if (rst) begin - state_reg <= STATE_IDLE; - s_axi_aready_reg <= 1'b0; - m_axi_avalid_reg <= 1'b0; - m_wc_valid_reg <= 1'b0; - m_rc_valid_reg <= 1'b0; - - trans_count_reg <= 0; - end else begin - state_reg <= state_next; - s_axi_aready_reg <= s_axi_aready_next; - m_axi_avalid_reg <= m_axi_avalid_next; - m_wc_valid_reg <= m_wc_valid_next; - m_rc_valid_reg <= m_rc_valid_next; - - if (trans_start && !trans_complete) begin - trans_count_reg <= trans_count_reg + 1; - end else if (!trans_start && trans_complete) begin - trans_count_reg <= trans_count_reg - 1; - end - end - - m_axi_aregion_reg <= m_axi_aregion_next; - m_select_reg <= m_select_next; - m_decerr_reg <= m_decerr_next; -end - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_rd.v b/xls/modules/zstd/external/axi_crossbar_rd.v deleted file mode 100644 index 2b1410ac62..0000000000 --- a/xls/modules/zstd/external/axi_crossbar_rd.v +++ /dev/null @@ -1,569 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 crossbar (read) - */ -module axi_crossbar_rd # -( - // Number of AXI inputs (slave interfaces) - parameter S_COUNT = 4, - // Number of AXI outputs (master interfaces) - parameter M_COUNT = 4, - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Input ID field width (from AXI masters) - parameter S_ID_WIDTH = 8, - // Output ID field width (towards AXI slaves) - // Additional bits required for response routing - parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), - // Propagate aruser signal - parameter ARUSER_ENABLE = 0, - // Width of aruser signal - parameter ARUSER_WIDTH = 1, - // Propagate ruser signal - parameter RUSER_ENABLE = 0, - // Width of ruser signal - parameter RUSER_WIDTH = 1, - // Number of concurrent unique IDs for each slave interface - // S_COUNT concatenated fields of 32 bits - parameter S_THREADS = {S_COUNT{32'd2}}, - // Number of concurrent operations for each slave interface - // S_COUNT concatenated fields of 32 bits - parameter S_ACCEPT = {S_COUNT{32'd16}}, - // Number of regions per master interface - parameter M_REGIONS = 1, - // Master interface base addresses - // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits - // set to zero for default addressing based on M_ADDR_WIDTH - parameter M_BASE_ADDR = 0, - // Master interface address widths - // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits - parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, - // Read connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}}, - // Number of concurrent operations for each master interface - // M_COUNT concatenated fields of 32 bits - parameter M_ISSUE = {M_COUNT{32'd4}}, - // Secure master (fail operations based on awprot/arprot) - // M_COUNT bits - parameter M_SECURE = {M_COUNT{1'b0}}, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_AR_REG_TYPE = {S_COUNT{2'd0}}, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_R_REG_TYPE = {S_COUNT{2'd2}}, - // Master interface AR channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_AR_REG_TYPE = {M_COUNT{2'd1}}, - // Master interface R channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_R_REG_TYPE = {M_COUNT{2'd0}} -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interfaces - */ - input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid, - input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr, - input wire [S_COUNT*8-1:0] s_axi_arlen, - input wire [S_COUNT*3-1:0] s_axi_arsize, - input wire [S_COUNT*2-1:0] s_axi_arburst, - input wire [S_COUNT-1:0] s_axi_arlock, - input wire [S_COUNT*4-1:0] s_axi_arcache, - input wire [S_COUNT*3-1:0] s_axi_arprot, - input wire [S_COUNT*4-1:0] s_axi_arqos, - input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser, - input wire [S_COUNT-1:0] s_axi_arvalid, - output wire [S_COUNT-1:0] s_axi_arready, - output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid, - output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata, - output wire [S_COUNT*2-1:0] s_axi_rresp, - output wire [S_COUNT-1:0] s_axi_rlast, - output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser, - output wire [S_COUNT-1:0] s_axi_rvalid, - input wire [S_COUNT-1:0] s_axi_rready, - - /* - * AXI master interfaces - */ - output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid, - output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr, - output wire [M_COUNT*8-1:0] m_axi_arlen, - output wire [M_COUNT*3-1:0] m_axi_arsize, - output wire [M_COUNT*2-1:0] m_axi_arburst, - output wire [M_COUNT-1:0] m_axi_arlock, - output wire [M_COUNT*4-1:0] m_axi_arcache, - output wire [M_COUNT*3-1:0] m_axi_arprot, - output wire [M_COUNT*4-1:0] m_axi_arqos, - output wire [M_COUNT*4-1:0] m_axi_arregion, - output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser, - output wire [M_COUNT-1:0] m_axi_arvalid, - input wire [M_COUNT-1:0] m_axi_arready, - input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid, - input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata, - input wire [M_COUNT*2-1:0] m_axi_rresp, - input wire [M_COUNT-1:0] m_axi_rlast, - input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser, - input wire [M_COUNT-1:0] m_axi_rvalid, - output wire [M_COUNT-1:0] m_axi_rready -); - -parameter CL_S_COUNT = $clog2(S_COUNT); -parameter CL_M_COUNT = $clog2(M_COUNT); -parameter M_COUNT_P1 = M_COUNT+1; -parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1); - -integer i; - -// check configuration -initial begin - if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin - $error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH (instance %m)"); - $finish; - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin - $error("Error: value out of range (instance %m)"); - $finish; - end - end -end - -wire [S_COUNT*S_ID_WIDTH-1:0] int_s_axi_arid; -wire [S_COUNT*ADDR_WIDTH-1:0] int_s_axi_araddr; -wire [S_COUNT*8-1:0] int_s_axi_arlen; -wire [S_COUNT*3-1:0] int_s_axi_arsize; -wire [S_COUNT*2-1:0] int_s_axi_arburst; -wire [S_COUNT-1:0] int_s_axi_arlock; -wire [S_COUNT*4-1:0] int_s_axi_arcache; -wire [S_COUNT*3-1:0] int_s_axi_arprot; -wire [S_COUNT*4-1:0] int_s_axi_arqos; -wire [S_COUNT*4-1:0] int_s_axi_arregion; -wire [S_COUNT*ARUSER_WIDTH-1:0] int_s_axi_aruser; -wire [S_COUNT-1:0] int_s_axi_arvalid; -wire [S_COUNT-1:0] int_s_axi_arready; - -wire [S_COUNT*M_COUNT-1:0] int_axi_arvalid; -wire [M_COUNT*S_COUNT-1:0] int_axi_arready; - -wire [M_COUNT*M_ID_WIDTH-1:0] int_m_axi_rid; -wire [M_COUNT*DATA_WIDTH-1:0] int_m_axi_rdata; -wire [M_COUNT*2-1:0] int_m_axi_rresp; -wire [M_COUNT-1:0] int_m_axi_rlast; -wire [M_COUNT*RUSER_WIDTH-1:0] int_m_axi_ruser; -wire [M_COUNT-1:0] int_m_axi_rvalid; -wire [M_COUNT-1:0] int_m_axi_rready; - -wire [M_COUNT*S_COUNT-1:0] int_axi_rvalid; -wire [S_COUNT*M_COUNT-1:0] int_axi_rready; - -generate - - genvar m, n; - - for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces - // address decode and admission control - wire [CL_M_COUNT-1:0] a_select; - - wire m_axi_avalid; - wire m_axi_aready; - - wire m_rc_decerr; - wire m_rc_valid; - wire m_rc_ready; - - wire [S_ID_WIDTH-1:0] s_cpl_id; - wire s_cpl_valid; - - axi_crossbar_addr #( - .S(m), - .S_COUNT(S_COUNT), - .M_COUNT(M_COUNT), - .ADDR_WIDTH(ADDR_WIDTH), - .ID_WIDTH(S_ID_WIDTH), - .S_THREADS(S_THREADS[m*32 +: 32]), - .S_ACCEPT(S_ACCEPT[m*32 +: 32]), - .M_REGIONS(M_REGIONS), - .M_BASE_ADDR(M_BASE_ADDR), - .M_ADDR_WIDTH(M_ADDR_WIDTH), - .M_CONNECT(M_CONNECT), - .M_SECURE(M_SECURE), - .WC_OUTPUT(0) - ) - addr_inst ( - .clk(clk), - .rst(rst), - - /* - * Address input - */ - .s_axi_aid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .s_axi_aaddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]), - .s_axi_aprot(int_s_axi_arprot[m*3 +: 3]), - .s_axi_aqos(int_s_axi_arqos[m*4 +: 4]), - .s_axi_avalid(int_s_axi_arvalid[m]), - .s_axi_aready(int_s_axi_arready[m]), - - /* - * Address output - */ - .m_axi_aregion(int_s_axi_arregion[m*4 +: 4]), - .m_select(a_select), - .m_axi_avalid(m_axi_avalid), - .m_axi_aready(m_axi_aready), - - /* - * Write command output - */ - .m_wc_select(), - .m_wc_decerr(), - .m_wc_valid(), - .m_wc_ready(1'b1), - - /* - * Response command output - */ - .m_rc_decerr(m_rc_decerr), - .m_rc_valid(m_rc_valid), - .m_rc_ready(m_rc_ready), - - /* - * Completion input - */ - .s_cpl_id(s_cpl_id), - .s_cpl_valid(s_cpl_valid) - ); - - assign int_axi_arvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select; - assign m_axi_aready = int_axi_arready[a_select*S_COUNT+m]; - - // decode error handling - reg [S_ID_WIDTH-1:0] decerr_m_axi_rid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_rid_next; - reg decerr_m_axi_rlast_reg = 1'b0, decerr_m_axi_rlast_next; - reg decerr_m_axi_rvalid_reg = 1'b0, decerr_m_axi_rvalid_next; - wire decerr_m_axi_rready; - - reg [7:0] decerr_len_reg = 8'd0, decerr_len_next; - - assign m_rc_ready = !decerr_m_axi_rvalid_reg; - - always @* begin - decerr_len_next = decerr_len_reg; - decerr_m_axi_rid_next = decerr_m_axi_rid_reg; - decerr_m_axi_rlast_next = decerr_m_axi_rlast_reg; - decerr_m_axi_rvalid_next = decerr_m_axi_rvalid_reg; - - if (decerr_m_axi_rvalid_reg) begin - if (decerr_m_axi_rready) begin - if (decerr_len_reg > 0) begin - decerr_len_next = decerr_len_reg-1; - decerr_m_axi_rlast_next = (decerr_len_next == 0); - decerr_m_axi_rvalid_next = 1'b1; - end else begin - decerr_m_axi_rvalid_next = 1'b0; - end - end - end else if (m_rc_valid && m_rc_ready) begin - decerr_len_next = int_s_axi_arlen[m*8 +: 8]; - decerr_m_axi_rid_next = int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]; - decerr_m_axi_rlast_next = (decerr_len_next == 0); - decerr_m_axi_rvalid_next = 1'b1; - end - end - - always @(posedge clk) begin - if (rst) begin - decerr_m_axi_rvalid_reg <= 1'b0; - end else begin - decerr_m_axi_rvalid_reg <= decerr_m_axi_rvalid_next; - end - - decerr_m_axi_rid_reg <= decerr_m_axi_rid_next; - decerr_m_axi_rlast_reg <= decerr_m_axi_rlast_next; - decerr_len_reg <= decerr_len_next; - end - - // read response arbitration - wire [M_COUNT_P1-1:0] r_request; - wire [M_COUNT_P1-1:0] r_acknowledge; - wire [M_COUNT_P1-1:0] r_grant; - wire r_grant_valid; - wire [CL_M_COUNT_P1-1:0] r_grant_encoded; - - arbiter #( - .PORTS(M_COUNT_P1), - .ARB_TYPE_ROUND_ROBIN(1), - .ARB_BLOCK(1), - .ARB_BLOCK_ACK(1), - .ARB_LSB_HIGH_PRIORITY(1) - ) - r_arb_inst ( - .clk(clk), - .rst(rst), - .request(r_request), - .acknowledge(r_acknowledge), - .grant(r_grant), - .grant_valid(r_grant_valid), - .grant_encoded(r_grant_encoded) - ); - - // read response mux - wire [S_ID_WIDTH-1:0] m_axi_rid_mux = {decerr_m_axi_rid_reg, int_m_axi_rid} >> r_grant_encoded*M_ID_WIDTH; - wire [DATA_WIDTH-1:0] m_axi_rdata_mux = {{DATA_WIDTH{1'b0}}, int_m_axi_rdata} >> r_grant_encoded*DATA_WIDTH; - wire [1:0] m_axi_rresp_mux = {2'b11, int_m_axi_rresp} >> r_grant_encoded*2; - wire m_axi_rlast_mux = {decerr_m_axi_rlast_reg, int_m_axi_rlast} >> r_grant_encoded; - wire [RUSER_WIDTH-1:0] m_axi_ruser_mux = {{RUSER_WIDTH{1'b0}}, int_m_axi_ruser} >> r_grant_encoded*RUSER_WIDTH; - wire m_axi_rvalid_mux = ({decerr_m_axi_rvalid_reg, int_m_axi_rvalid} >> r_grant_encoded) & r_grant_valid; - wire m_axi_rready_mux; - - assign int_axi_rready[m*M_COUNT +: M_COUNT] = (r_grant_valid && m_axi_rready_mux) << r_grant_encoded; - assign decerr_m_axi_rready = (r_grant_valid && m_axi_rready_mux) && (r_grant_encoded == M_COUNT_P1-1); - - for (n = 0; n < M_COUNT; n = n + 1) begin - assign r_request[n] = int_axi_rvalid[n*S_COUNT+m] && !r_grant[n]; - assign r_acknowledge[n] = r_grant[n] && int_axi_rvalid[n*S_COUNT+m] && m_axi_rlast_mux && m_axi_rready_mux; - end - - assign r_request[M_COUNT_P1-1] = decerr_m_axi_rvalid_reg && !r_grant[M_COUNT_P1-1]; - assign r_acknowledge[M_COUNT_P1-1] = r_grant[M_COUNT_P1-1] && decerr_m_axi_rvalid_reg && decerr_m_axi_rlast_reg && m_axi_rready_mux; - - assign s_cpl_id = m_axi_rid_mux; - assign s_cpl_valid = m_axi_rvalid_mux && m_axi_rready_mux && m_axi_rlast_mux; - - // S side register - axi_register_rd #( - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .ID_WIDTH(S_ID_WIDTH), - .ARUSER_ENABLE(ARUSER_ENABLE), - .ARUSER_WIDTH(ARUSER_WIDTH), - .RUSER_ENABLE(RUSER_ENABLE), - .RUSER_WIDTH(RUSER_WIDTH), - .AR_REG_TYPE(S_AR_REG_TYPE[m*2 +: 2]), - .R_REG_TYPE(S_R_REG_TYPE[m*2 +: 2]) - ) - reg_inst ( - .clk(clk), - .rst(rst), - .s_axi_arid(s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .s_axi_araddr(s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]), - .s_axi_arlen(s_axi_arlen[m*8 +: 8]), - .s_axi_arsize(s_axi_arsize[m*3 +: 3]), - .s_axi_arburst(s_axi_arburst[m*2 +: 2]), - .s_axi_arlock(s_axi_arlock[m]), - .s_axi_arcache(s_axi_arcache[m*4 +: 4]), - .s_axi_arprot(s_axi_arprot[m*3 +: 3]), - .s_axi_arqos(s_axi_arqos[m*4 +: 4]), - .s_axi_arregion(4'd0), - .s_axi_aruser(s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]), - .s_axi_arvalid(s_axi_arvalid[m]), - .s_axi_arready(s_axi_arready[m]), - .s_axi_rid(s_axi_rid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .s_axi_rdata(s_axi_rdata[m*DATA_WIDTH +: DATA_WIDTH]), - .s_axi_rresp(s_axi_rresp[m*2 +: 2]), - .s_axi_rlast(s_axi_rlast[m]), - .s_axi_ruser(s_axi_ruser[m*RUSER_WIDTH +: RUSER_WIDTH]), - .s_axi_rvalid(s_axi_rvalid[m]), - .s_axi_rready(s_axi_rready[m]), - .m_axi_arid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .m_axi_araddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]), - .m_axi_arlen(int_s_axi_arlen[m*8 +: 8]), - .m_axi_arsize(int_s_axi_arsize[m*3 +: 3]), - .m_axi_arburst(int_s_axi_arburst[m*2 +: 2]), - .m_axi_arlock(int_s_axi_arlock[m]), - .m_axi_arcache(int_s_axi_arcache[m*4 +: 4]), - .m_axi_arprot(int_s_axi_arprot[m*3 +: 3]), - .m_axi_arqos(int_s_axi_arqos[m*4 +: 4]), - .m_axi_arregion(), - .m_axi_aruser(int_s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]), - .m_axi_arvalid(int_s_axi_arvalid[m]), - .m_axi_arready(int_s_axi_arready[m]), - .m_axi_rid(m_axi_rid_mux), - .m_axi_rdata(m_axi_rdata_mux), - .m_axi_rresp(m_axi_rresp_mux), - .m_axi_rlast(m_axi_rlast_mux), - .m_axi_ruser(m_axi_ruser_mux), - .m_axi_rvalid(m_axi_rvalid_mux), - .m_axi_rready(m_axi_rready_mux) - ); - end // s_ifaces - - for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces - // in-flight transaction count - wire trans_start; - wire trans_complete; - reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0; - - wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete; - - always @(posedge clk) begin - if (rst) begin - trans_count_reg <= 0; - end else begin - if (trans_start && !trans_complete) begin - trans_count_reg <= trans_count_reg + 1; - end else if (!trans_start && trans_complete) begin - trans_count_reg <= trans_count_reg - 1; - end - end - end - - // address arbitration - wire [S_COUNT-1:0] a_request; - wire [S_COUNT-1:0] a_acknowledge; - wire [S_COUNT-1:0] a_grant; - wire a_grant_valid; - wire [CL_S_COUNT-1:0] a_grant_encoded; - - arbiter #( - .PORTS(S_COUNT), - .ARB_TYPE_ROUND_ROBIN(1), - .ARB_BLOCK(1), - .ARB_BLOCK_ACK(1), - .ARB_LSB_HIGH_PRIORITY(1) - ) - a_arb_inst ( - .clk(clk), - .rst(rst), - .request(a_request), - .acknowledge(a_acknowledge), - .grant(a_grant), - .grant_valid(a_grant_valid), - .grant_encoded(a_grant_encoded) - ); - - // address mux - wire [M_ID_WIDTH-1:0] s_axi_arid_mux = int_s_axi_arid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH); - wire [ADDR_WIDTH-1:0] s_axi_araddr_mux = int_s_axi_araddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH]; - wire [7:0] s_axi_arlen_mux = int_s_axi_arlen[a_grant_encoded*8 +: 8]; - wire [2:0] s_axi_arsize_mux = int_s_axi_arsize[a_grant_encoded*3 +: 3]; - wire [1:0] s_axi_arburst_mux = int_s_axi_arburst[a_grant_encoded*2 +: 2]; - wire s_axi_arlock_mux = int_s_axi_arlock[a_grant_encoded]; - wire [3:0] s_axi_arcache_mux = int_s_axi_arcache[a_grant_encoded*4 +: 4]; - wire [2:0] s_axi_arprot_mux = int_s_axi_arprot[a_grant_encoded*3 +: 3]; - wire [3:0] s_axi_arqos_mux = int_s_axi_arqos[a_grant_encoded*4 +: 4]; - wire [3:0] s_axi_arregion_mux = int_s_axi_arregion[a_grant_encoded*4 +: 4]; - wire [ARUSER_WIDTH-1:0] s_axi_aruser_mux = int_s_axi_aruser[a_grant_encoded*ARUSER_WIDTH +: ARUSER_WIDTH]; - wire s_axi_arvalid_mux = int_axi_arvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid; - wire s_axi_arready_mux; - - assign int_axi_arready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_arready_mux) << a_grant_encoded; - - for (m = 0; m < S_COUNT; m = m + 1) begin - assign a_request[m] = int_axi_arvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit; - assign a_acknowledge[m] = a_grant[m] && int_axi_arvalid[m*M_COUNT+n] && s_axi_arready_mux; - end - - assign trans_start = s_axi_arvalid_mux && s_axi_arready_mux && a_grant_valid; - - // read response forwarding - wire [CL_S_COUNT-1:0] r_select = m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH; - - assign int_axi_rvalid[n*S_COUNT +: S_COUNT] = int_m_axi_rvalid[n] << r_select; - assign int_m_axi_rready[n] = int_axi_rready[r_select*M_COUNT+n]; - - assign trans_complete = int_m_axi_rvalid[n] && int_m_axi_rready[n] && int_m_axi_rlast[n]; - - // M side register - axi_register_rd #( - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .ID_WIDTH(M_ID_WIDTH), - .ARUSER_ENABLE(ARUSER_ENABLE), - .ARUSER_WIDTH(ARUSER_WIDTH), - .RUSER_ENABLE(RUSER_ENABLE), - .RUSER_WIDTH(RUSER_WIDTH), - .AR_REG_TYPE(M_AR_REG_TYPE[n*2 +: 2]), - .R_REG_TYPE(M_R_REG_TYPE[n*2 +: 2]) - ) - reg_inst ( - .clk(clk), - .rst(rst), - .s_axi_arid(s_axi_arid_mux), - .s_axi_araddr(s_axi_araddr_mux), - .s_axi_arlen(s_axi_arlen_mux), - .s_axi_arsize(s_axi_arsize_mux), - .s_axi_arburst(s_axi_arburst_mux), - .s_axi_arlock(s_axi_arlock_mux), - .s_axi_arcache(s_axi_arcache_mux), - .s_axi_arprot(s_axi_arprot_mux), - .s_axi_arqos(s_axi_arqos_mux), - .s_axi_arregion(s_axi_arregion_mux), - .s_axi_aruser(s_axi_aruser_mux), - .s_axi_arvalid(s_axi_arvalid_mux), - .s_axi_arready(s_axi_arready_mux), - .s_axi_rid(int_m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]), - .s_axi_rdata(int_m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]), - .s_axi_rresp(int_m_axi_rresp[n*2 +: 2]), - .s_axi_rlast(int_m_axi_rlast[n]), - .s_axi_ruser(int_m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]), - .s_axi_rvalid(int_m_axi_rvalid[n]), - .s_axi_rready(int_m_axi_rready[n]), - .m_axi_arid(m_axi_arid[n*M_ID_WIDTH +: M_ID_WIDTH]), - .m_axi_araddr(m_axi_araddr[n*ADDR_WIDTH +: ADDR_WIDTH]), - .m_axi_arlen(m_axi_arlen[n*8 +: 8]), - .m_axi_arsize(m_axi_arsize[n*3 +: 3]), - .m_axi_arburst(m_axi_arburst[n*2 +: 2]), - .m_axi_arlock(m_axi_arlock[n]), - .m_axi_arcache(m_axi_arcache[n*4 +: 4]), - .m_axi_arprot(m_axi_arprot[n*3 +: 3]), - .m_axi_arqos(m_axi_arqos[n*4 +: 4]), - .m_axi_arregion(m_axi_arregion[n*4 +: 4]), - .m_axi_aruser(m_axi_aruser[n*ARUSER_WIDTH +: ARUSER_WIDTH]), - .m_axi_arvalid(m_axi_arvalid[n]), - .m_axi_arready(m_axi_arready[n]), - .m_axi_rid(m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]), - .m_axi_rdata(m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]), - .m_axi_rresp(m_axi_rresp[n*2 +: 2]), - .m_axi_rlast(m_axi_rlast[n]), - .m_axi_ruser(m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]), - .m_axi_rvalid(m_axi_rvalid[n]), - .m_axi_rready(m_axi_rready[n]) - ); - end // m_ifaces - -endgenerate - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_wr.v b/xls/modules/zstd/external/axi_crossbar_wr.v deleted file mode 100644 index 5f55665351..0000000000 --- a/xls/modules/zstd/external/axi_crossbar_wr.v +++ /dev/null @@ -1,678 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 crossbar (write) - */ -module axi_crossbar_wr # -( - // Number of AXI inputs (slave interfaces) - parameter S_COUNT = 4, - // Number of AXI outputs (master interfaces) - parameter M_COUNT = 4, - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Input ID field width (from AXI masters) - parameter S_ID_WIDTH = 8, - // Output ID field width (towards AXI slaves) - // Additional bits required for response routing - parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), - // Propagate awuser signal - parameter AWUSER_ENABLE = 0, - // Width of awuser signal - parameter AWUSER_WIDTH = 1, - // Propagate wuser signal - parameter WUSER_ENABLE = 0, - // Width of wuser signal - parameter WUSER_WIDTH = 1, - // Propagate buser signal - parameter BUSER_ENABLE = 0, - // Width of buser signal - parameter BUSER_WIDTH = 1, - // Number of concurrent unique IDs for each slave interface - // S_COUNT concatenated fields of 32 bits - parameter S_THREADS = {S_COUNT{32'd2}}, - // Number of concurrent operations for each slave interface - // S_COUNT concatenated fields of 32 bits - parameter S_ACCEPT = {S_COUNT{32'd16}}, - // Number of regions per master interface - parameter M_REGIONS = 1, - // Master interface base addresses - // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits - // set to zero for default addressing based on M_ADDR_WIDTH - parameter M_BASE_ADDR = 0, - // Master interface address widths - // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits - parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, - // Write connections between interfaces - // M_COUNT concatenated fields of S_COUNT bits - parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}}, - // Number of concurrent operations for each master interface - // M_COUNT concatenated fields of 32 bits - parameter M_ISSUE = {M_COUNT{32'd4}}, - // Secure master (fail operations based on awprot/arprot) - // M_COUNT bits - parameter M_SECURE = {M_COUNT{1'b0}}, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_AW_REG_TYPE = {S_COUNT{2'd0}}, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_W_REG_TYPE = {S_COUNT{2'd0}}, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S_B_REG_TYPE = {S_COUNT{2'd1}}, - // Master interface AW channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_AW_REG_TYPE = {M_COUNT{2'd1}}, - // Master interface W channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_W_REG_TYPE = {M_COUNT{2'd2}}, - // Master interface B channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M_B_REG_TYPE = {M_COUNT{2'd0}} -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interfaces - */ - input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid, - input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr, - input wire [S_COUNT*8-1:0] s_axi_awlen, - input wire [S_COUNT*3-1:0] s_axi_awsize, - input wire [S_COUNT*2-1:0] s_axi_awburst, - input wire [S_COUNT-1:0] s_axi_awlock, - input wire [S_COUNT*4-1:0] s_axi_awcache, - input wire [S_COUNT*3-1:0] s_axi_awprot, - input wire [S_COUNT*4-1:0] s_axi_awqos, - input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser, - input wire [S_COUNT-1:0] s_axi_awvalid, - output wire [S_COUNT-1:0] s_axi_awready, - input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata, - input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb, - input wire [S_COUNT-1:0] s_axi_wlast, - input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser, - input wire [S_COUNT-1:0] s_axi_wvalid, - output wire [S_COUNT-1:0] s_axi_wready, - output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid, - output wire [S_COUNT*2-1:0] s_axi_bresp, - output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser, - output wire [S_COUNT-1:0] s_axi_bvalid, - input wire [S_COUNT-1:0] s_axi_bready, - - /* - * AXI master interfaces - */ - output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid, - output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr, - output wire [M_COUNT*8-1:0] m_axi_awlen, - output wire [M_COUNT*3-1:0] m_axi_awsize, - output wire [M_COUNT*2-1:0] m_axi_awburst, - output wire [M_COUNT-1:0] m_axi_awlock, - output wire [M_COUNT*4-1:0] m_axi_awcache, - output wire [M_COUNT*3-1:0] m_axi_awprot, - output wire [M_COUNT*4-1:0] m_axi_awqos, - output wire [M_COUNT*4-1:0] m_axi_awregion, - output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser, - output wire [M_COUNT-1:0] m_axi_awvalid, - input wire [M_COUNT-1:0] m_axi_awready, - output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata, - output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb, - output wire [M_COUNT-1:0] m_axi_wlast, - output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser, - output wire [M_COUNT-1:0] m_axi_wvalid, - input wire [M_COUNT-1:0] m_axi_wready, - input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid, - input wire [M_COUNT*2-1:0] m_axi_bresp, - input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser, - input wire [M_COUNT-1:0] m_axi_bvalid, - output wire [M_COUNT-1:0] m_axi_bready -); - -parameter CL_S_COUNT = $clog2(S_COUNT); -parameter CL_M_COUNT = $clog2(M_COUNT); -parameter M_COUNT_P1 = M_COUNT+1; -parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1); - -integer i; - -// check configuration -initial begin - if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin - $error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH (instance %m)"); - $finish; - end - - for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin - if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin - $error("Error: value out of range (instance %m)"); - $finish; - end - end -end - -wire [S_COUNT*S_ID_WIDTH-1:0] int_s_axi_awid; -wire [S_COUNT*ADDR_WIDTH-1:0] int_s_axi_awaddr; -wire [S_COUNT*8-1:0] int_s_axi_awlen; -wire [S_COUNT*3-1:0] int_s_axi_awsize; -wire [S_COUNT*2-1:0] int_s_axi_awburst; -wire [S_COUNT-1:0] int_s_axi_awlock; -wire [S_COUNT*4-1:0] int_s_axi_awcache; -wire [S_COUNT*3-1:0] int_s_axi_awprot; -wire [S_COUNT*4-1:0] int_s_axi_awqos; -wire [S_COUNT*4-1:0] int_s_axi_awregion; -wire [S_COUNT*AWUSER_WIDTH-1:0] int_s_axi_awuser; -wire [S_COUNT-1:0] int_s_axi_awvalid; -wire [S_COUNT-1:0] int_s_axi_awready; - -wire [S_COUNT*M_COUNT-1:0] int_axi_awvalid; -wire [M_COUNT*S_COUNT-1:0] int_axi_awready; - -wire [S_COUNT*DATA_WIDTH-1:0] int_s_axi_wdata; -wire [S_COUNT*STRB_WIDTH-1:0] int_s_axi_wstrb; -wire [S_COUNT-1:0] int_s_axi_wlast; -wire [S_COUNT*WUSER_WIDTH-1:0] int_s_axi_wuser; -wire [S_COUNT-1:0] int_s_axi_wvalid; -wire [S_COUNT-1:0] int_s_axi_wready; - -wire [S_COUNT*M_COUNT-1:0] int_axi_wvalid; -wire [M_COUNT*S_COUNT-1:0] int_axi_wready; - -wire [M_COUNT*M_ID_WIDTH-1:0] int_m_axi_bid; -wire [M_COUNT*2-1:0] int_m_axi_bresp; -wire [M_COUNT*BUSER_WIDTH-1:0] int_m_axi_buser; -wire [M_COUNT-1:0] int_m_axi_bvalid; -wire [M_COUNT-1:0] int_m_axi_bready; - -wire [M_COUNT*S_COUNT-1:0] int_axi_bvalid; -wire [S_COUNT*M_COUNT-1:0] int_axi_bready; - -generate - - genvar m, n; - - for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces - // address decode and admission control - wire [CL_M_COUNT-1:0] a_select; - - wire m_axi_avalid; - wire m_axi_aready; - - wire [CL_M_COUNT-1:0] m_wc_select; - wire m_wc_decerr; - wire m_wc_valid; - wire m_wc_ready; - - wire m_rc_decerr; - wire m_rc_valid; - wire m_rc_ready; - - wire [S_ID_WIDTH-1:0] s_cpl_id; - wire s_cpl_valid; - - axi_crossbar_addr #( - .S(m), - .S_COUNT(S_COUNT), - .M_COUNT(M_COUNT), - .ADDR_WIDTH(ADDR_WIDTH), - .ID_WIDTH(S_ID_WIDTH), - .S_THREADS(S_THREADS[m*32 +: 32]), - .S_ACCEPT(S_ACCEPT[m*32 +: 32]), - .M_REGIONS(M_REGIONS), - .M_BASE_ADDR(M_BASE_ADDR), - .M_ADDR_WIDTH(M_ADDR_WIDTH), - .M_CONNECT(M_CONNECT), - .M_SECURE(M_SECURE), - .WC_OUTPUT(1) - ) - addr_inst ( - .clk(clk), - .rst(rst), - - /* - * Address input - */ - .s_axi_aid(int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .s_axi_aaddr(int_s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]), - .s_axi_aprot(int_s_axi_awprot[m*3 +: 3]), - .s_axi_aqos(int_s_axi_awqos[m*4 +: 4]), - .s_axi_avalid(int_s_axi_awvalid[m]), - .s_axi_aready(int_s_axi_awready[m]), - - /* - * Address output - */ - .m_axi_aregion(int_s_axi_awregion[m*4 +: 4]), - .m_select(a_select), - .m_axi_avalid(m_axi_avalid), - .m_axi_aready(m_axi_aready), - - /* - * Write command output - */ - .m_wc_select(m_wc_select), - .m_wc_decerr(m_wc_decerr), - .m_wc_valid(m_wc_valid), - .m_wc_ready(m_wc_ready), - - /* - * Response command output - */ - .m_rc_decerr(m_rc_decerr), - .m_rc_valid(m_rc_valid), - .m_rc_ready(m_rc_ready), - - /* - * Completion input - */ - .s_cpl_id(s_cpl_id), - .s_cpl_valid(s_cpl_valid) - ); - - assign int_axi_awvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select; - assign m_axi_aready = int_axi_awready[a_select*S_COUNT+m]; - - // write command handling - reg [CL_M_COUNT-1:0] w_select_reg = 0, w_select_next; - reg w_drop_reg = 1'b0, w_drop_next; - reg w_select_valid_reg = 1'b0, w_select_valid_next; - - assign m_wc_ready = !w_select_valid_reg; - - always @* begin - w_select_next = w_select_reg; - w_drop_next = w_drop_reg && !(int_s_axi_wvalid[m] && int_s_axi_wready[m] && int_s_axi_wlast[m]); - w_select_valid_next = w_select_valid_reg && !(int_s_axi_wvalid[m] && int_s_axi_wready[m] && int_s_axi_wlast[m]); - - if (m_wc_valid && !w_select_valid_reg) begin - w_select_next = m_wc_select; - w_drop_next = m_wc_decerr; - w_select_valid_next = m_wc_valid; - end - end - - always @(posedge clk) begin - if (rst) begin - w_select_valid_reg <= 1'b0; - end else begin - w_select_valid_reg <= w_select_valid_next; - end - - w_select_reg <= w_select_next; - w_drop_reg <= w_drop_next; - end - - // write data forwarding - assign int_axi_wvalid[m*M_COUNT +: M_COUNT] = (int_s_axi_wvalid[m] && w_select_valid_reg && !w_drop_reg) << w_select_reg; - assign int_s_axi_wready[m] = int_axi_wready[w_select_reg*S_COUNT+m] || w_drop_reg; - - // decode error handling - reg [S_ID_WIDTH-1:0] decerr_m_axi_bid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_bid_next; - reg decerr_m_axi_bvalid_reg = 1'b0, decerr_m_axi_bvalid_next; - wire decerr_m_axi_bready; - - assign m_rc_ready = !decerr_m_axi_bvalid_reg; - - always @* begin - decerr_m_axi_bid_next = decerr_m_axi_bid_reg; - decerr_m_axi_bvalid_next = decerr_m_axi_bvalid_reg; - - if (decerr_m_axi_bvalid_reg) begin - if (decerr_m_axi_bready) begin - decerr_m_axi_bvalid_next = 1'b0; - end - end else if (m_rc_valid && m_rc_ready) begin - decerr_m_axi_bid_next = int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]; - decerr_m_axi_bvalid_next = 1'b1; - end - end - - always @(posedge clk) begin - if (rst) begin - decerr_m_axi_bvalid_reg <= 1'b0; - end else begin - decerr_m_axi_bvalid_reg <= decerr_m_axi_bvalid_next; - end - - decerr_m_axi_bid_reg <= decerr_m_axi_bid_next; - end - - // write response arbitration - wire [M_COUNT_P1-1:0] b_request; - wire [M_COUNT_P1-1:0] b_acknowledge; - wire [M_COUNT_P1-1:0] b_grant; - wire b_grant_valid; - wire [CL_M_COUNT_P1-1:0] b_grant_encoded; - - arbiter #( - .PORTS(M_COUNT_P1), - .ARB_TYPE_ROUND_ROBIN(1), - .ARB_BLOCK(1), - .ARB_BLOCK_ACK(1), - .ARB_LSB_HIGH_PRIORITY(1) - ) - b_arb_inst ( - .clk(clk), - .rst(rst), - .request(b_request), - .acknowledge(b_acknowledge), - .grant(b_grant), - .grant_valid(b_grant_valid), - .grant_encoded(b_grant_encoded) - ); - - // write response mux - wire [S_ID_WIDTH-1:0] m_axi_bid_mux = {decerr_m_axi_bid_reg, int_m_axi_bid} >> b_grant_encoded*M_ID_WIDTH; - wire [1:0] m_axi_bresp_mux = {2'b11, int_m_axi_bresp} >> b_grant_encoded*2; - wire [BUSER_WIDTH-1:0] m_axi_buser_mux = {{BUSER_WIDTH{1'b0}}, int_m_axi_buser} >> b_grant_encoded*BUSER_WIDTH; - wire m_axi_bvalid_mux = ({decerr_m_axi_bvalid_reg, int_m_axi_bvalid} >> b_grant_encoded) & b_grant_valid; - wire m_axi_bready_mux; - - assign int_axi_bready[m*M_COUNT +: M_COUNT] = (b_grant_valid && m_axi_bready_mux) << b_grant_encoded; - assign decerr_m_axi_bready = (b_grant_valid && m_axi_bready_mux) && (b_grant_encoded == M_COUNT_P1-1); - - for (n = 0; n < M_COUNT; n = n + 1) begin - assign b_request[n] = int_axi_bvalid[n*S_COUNT+m] && !b_grant[n]; - assign b_acknowledge[n] = b_grant[n] && int_axi_bvalid[n*S_COUNT+m] && m_axi_bready_mux; - end - - assign b_request[M_COUNT_P1-1] = decerr_m_axi_bvalid_reg && !b_grant[M_COUNT_P1-1]; - assign b_acknowledge[M_COUNT_P1-1] = b_grant[M_COUNT_P1-1] && decerr_m_axi_bvalid_reg && m_axi_bready_mux; - - assign s_cpl_id = m_axi_bid_mux; - assign s_cpl_valid = m_axi_bvalid_mux && m_axi_bready_mux; - - // S side register - axi_register_wr #( - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .ID_WIDTH(S_ID_WIDTH), - .AWUSER_ENABLE(AWUSER_ENABLE), - .AWUSER_WIDTH(AWUSER_WIDTH), - .WUSER_ENABLE(WUSER_ENABLE), - .WUSER_WIDTH(WUSER_WIDTH), - .BUSER_ENABLE(BUSER_ENABLE), - .BUSER_WIDTH(BUSER_WIDTH), - .AW_REG_TYPE(S_AW_REG_TYPE[m*2 +: 2]), - .W_REG_TYPE(S_W_REG_TYPE[m*2 +: 2]), - .B_REG_TYPE(S_B_REG_TYPE[m*2 +: 2]) - ) - reg_inst ( - .clk(clk), - .rst(rst), - .s_axi_awid(s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .s_axi_awaddr(s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]), - .s_axi_awlen(s_axi_awlen[m*8 +: 8]), - .s_axi_awsize(s_axi_awsize[m*3 +: 3]), - .s_axi_awburst(s_axi_awburst[m*2 +: 2]), - .s_axi_awlock(s_axi_awlock[m]), - .s_axi_awcache(s_axi_awcache[m*4 +: 4]), - .s_axi_awprot(s_axi_awprot[m*3 +: 3]), - .s_axi_awqos(s_axi_awqos[m*4 +: 4]), - .s_axi_awregion(4'd0), - .s_axi_awuser(s_axi_awuser[m*AWUSER_WIDTH +: AWUSER_WIDTH]), - .s_axi_awvalid(s_axi_awvalid[m]), - .s_axi_awready(s_axi_awready[m]), - .s_axi_wdata(s_axi_wdata[m*DATA_WIDTH +: DATA_WIDTH]), - .s_axi_wstrb(s_axi_wstrb[m*STRB_WIDTH +: STRB_WIDTH]), - .s_axi_wlast(s_axi_wlast[m]), - .s_axi_wuser(s_axi_wuser[m*WUSER_WIDTH +: WUSER_WIDTH]), - .s_axi_wvalid(s_axi_wvalid[m]), - .s_axi_wready(s_axi_wready[m]), - .s_axi_bid(s_axi_bid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .s_axi_bresp(s_axi_bresp[m*2 +: 2]), - .s_axi_buser(s_axi_buser[m*BUSER_WIDTH +: BUSER_WIDTH]), - .s_axi_bvalid(s_axi_bvalid[m]), - .s_axi_bready(s_axi_bready[m]), - .m_axi_awid(int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]), - .m_axi_awaddr(int_s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]), - .m_axi_awlen(int_s_axi_awlen[m*8 +: 8]), - .m_axi_awsize(int_s_axi_awsize[m*3 +: 3]), - .m_axi_awburst(int_s_axi_awburst[m*2 +: 2]), - .m_axi_awlock(int_s_axi_awlock[m]), - .m_axi_awcache(int_s_axi_awcache[m*4 +: 4]), - .m_axi_awprot(int_s_axi_awprot[m*3 +: 3]), - .m_axi_awqos(int_s_axi_awqos[m*4 +: 4]), - .m_axi_awregion(), - .m_axi_awuser(int_s_axi_awuser[m*AWUSER_WIDTH +: AWUSER_WIDTH]), - .m_axi_awvalid(int_s_axi_awvalid[m]), - .m_axi_awready(int_s_axi_awready[m]), - .m_axi_wdata(int_s_axi_wdata[m*DATA_WIDTH +: DATA_WIDTH]), - .m_axi_wstrb(int_s_axi_wstrb[m*STRB_WIDTH +: STRB_WIDTH]), - .m_axi_wlast(int_s_axi_wlast[m]), - .m_axi_wuser(int_s_axi_wuser[m*WUSER_WIDTH +: WUSER_WIDTH]), - .m_axi_wvalid(int_s_axi_wvalid[m]), - .m_axi_wready(int_s_axi_wready[m]), - .m_axi_bid(m_axi_bid_mux), - .m_axi_bresp(m_axi_bresp_mux), - .m_axi_buser(m_axi_buser_mux), - .m_axi_bvalid(m_axi_bvalid_mux), - .m_axi_bready(m_axi_bready_mux) - ); - end // s_ifaces - - for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces - // in-flight transaction count - wire trans_start; - wire trans_complete; - reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0; - - wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete; - - always @(posedge clk) begin - if (rst) begin - trans_count_reg <= 0; - end else begin - if (trans_start && !trans_complete) begin - trans_count_reg <= trans_count_reg + 1; - end else if (!trans_start && trans_complete) begin - trans_count_reg <= trans_count_reg - 1; - end - end - end - - // address arbitration - reg [CL_S_COUNT-1:0] w_select_reg = 0, w_select_next; - reg w_select_valid_reg = 1'b0, w_select_valid_next; - reg w_select_new_reg = 1'b0, w_select_new_next; - - wire [S_COUNT-1:0] a_request; - wire [S_COUNT-1:0] a_acknowledge; - wire [S_COUNT-1:0] a_grant; - wire a_grant_valid; - wire [CL_S_COUNT-1:0] a_grant_encoded; - - arbiter #( - .PORTS(S_COUNT), - .ARB_TYPE_ROUND_ROBIN(1), - .ARB_BLOCK(1), - .ARB_BLOCK_ACK(1), - .ARB_LSB_HIGH_PRIORITY(1) - ) - a_arb_inst ( - .clk(clk), - .rst(rst), - .request(a_request), - .acknowledge(a_acknowledge), - .grant(a_grant), - .grant_valid(a_grant_valid), - .grant_encoded(a_grant_encoded) - ); - - // address mux - wire [M_ID_WIDTH-1:0] s_axi_awid_mux = int_s_axi_awid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH); - wire [ADDR_WIDTH-1:0] s_axi_awaddr_mux = int_s_axi_awaddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH]; - wire [7:0] s_axi_awlen_mux = int_s_axi_awlen[a_grant_encoded*8 +: 8]; - wire [2:0] s_axi_awsize_mux = int_s_axi_awsize[a_grant_encoded*3 +: 3]; - wire [1:0] s_axi_awburst_mux = int_s_axi_awburst[a_grant_encoded*2 +: 2]; - wire s_axi_awlock_mux = int_s_axi_awlock[a_grant_encoded]; - wire [3:0] s_axi_awcache_mux = int_s_axi_awcache[a_grant_encoded*4 +: 4]; - wire [2:0] s_axi_awprot_mux = int_s_axi_awprot[a_grant_encoded*3 +: 3]; - wire [3:0] s_axi_awqos_mux = int_s_axi_awqos[a_grant_encoded*4 +: 4]; - wire [3:0] s_axi_awregion_mux = int_s_axi_awregion[a_grant_encoded*4 +: 4]; - wire [AWUSER_WIDTH-1:0] s_axi_awuser_mux = int_s_axi_awuser[a_grant_encoded*AWUSER_WIDTH +: AWUSER_WIDTH]; - wire s_axi_awvalid_mux = int_axi_awvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid; - wire s_axi_awready_mux; - - assign int_axi_awready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_awready_mux) << a_grant_encoded; - - for (m = 0; m < S_COUNT; m = m + 1) begin - assign a_request[m] = int_axi_awvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit && !w_select_valid_next; - assign a_acknowledge[m] = a_grant[m] && int_axi_awvalid[m*M_COUNT+n] && s_axi_awready_mux; - end - - assign trans_start = s_axi_awvalid_mux && s_axi_awready_mux && a_grant_valid; - - // write data mux - wire [DATA_WIDTH-1:0] s_axi_wdata_mux = int_s_axi_wdata[w_select_reg*DATA_WIDTH +: DATA_WIDTH]; - wire [STRB_WIDTH-1:0] s_axi_wstrb_mux = int_s_axi_wstrb[w_select_reg*STRB_WIDTH +: STRB_WIDTH]; - wire s_axi_wlast_mux = int_s_axi_wlast[w_select_reg]; - wire [WUSER_WIDTH-1:0] s_axi_wuser_mux = int_s_axi_wuser[w_select_reg*WUSER_WIDTH +: WUSER_WIDTH]; - wire s_axi_wvalid_mux = int_axi_wvalid[w_select_reg*M_COUNT+n] && w_select_valid_reg; - wire s_axi_wready_mux; - - assign int_axi_wready[n*S_COUNT +: S_COUNT] = (w_select_valid_reg && s_axi_wready_mux) << w_select_reg; - - // write data routing - always @* begin - w_select_next = w_select_reg; - w_select_valid_next = w_select_valid_reg && !(s_axi_wvalid_mux && s_axi_wready_mux && s_axi_wlast_mux); - w_select_new_next = w_select_new_reg || !a_grant_valid || a_acknowledge; - - if (a_grant_valid && !w_select_valid_reg && w_select_new_reg) begin - w_select_next = a_grant_encoded; - w_select_valid_next = a_grant_valid; - w_select_new_next = 1'b0; - end - end - - always @(posedge clk) begin - if (rst) begin - w_select_valid_reg <= 1'b0; - w_select_new_reg <= 1'b1; - end else begin - w_select_valid_reg <= w_select_valid_next; - w_select_new_reg <= w_select_new_next; - end - - w_select_reg <= w_select_next; - end - - // write response forwarding - wire [CL_S_COUNT-1:0] b_select = m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH; - - assign int_axi_bvalid[n*S_COUNT +: S_COUNT] = int_m_axi_bvalid[n] << b_select; - assign int_m_axi_bready[n] = int_axi_bready[b_select*M_COUNT+n]; - - assign trans_complete = int_m_axi_bvalid[n] && int_m_axi_bready[n]; - - // M side register - axi_register_wr #( - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .ID_WIDTH(M_ID_WIDTH), - .AWUSER_ENABLE(AWUSER_ENABLE), - .AWUSER_WIDTH(AWUSER_WIDTH), - .WUSER_ENABLE(WUSER_ENABLE), - .WUSER_WIDTH(WUSER_WIDTH), - .BUSER_ENABLE(BUSER_ENABLE), - .BUSER_WIDTH(BUSER_WIDTH), - .AW_REG_TYPE(M_AW_REG_TYPE[n*2 +: 2]), - .W_REG_TYPE(M_W_REG_TYPE[n*2 +: 2]), - .B_REG_TYPE(M_B_REG_TYPE[n*2 +: 2]) - ) - reg_inst ( - .clk(clk), - .rst(rst), - .s_axi_awid(s_axi_awid_mux), - .s_axi_awaddr(s_axi_awaddr_mux), - .s_axi_awlen(s_axi_awlen_mux), - .s_axi_awsize(s_axi_awsize_mux), - .s_axi_awburst(s_axi_awburst_mux), - .s_axi_awlock(s_axi_awlock_mux), - .s_axi_awcache(s_axi_awcache_mux), - .s_axi_awprot(s_axi_awprot_mux), - .s_axi_awqos(s_axi_awqos_mux), - .s_axi_awregion(s_axi_awregion_mux), - .s_axi_awuser(s_axi_awuser_mux), - .s_axi_awvalid(s_axi_awvalid_mux), - .s_axi_awready(s_axi_awready_mux), - .s_axi_wdata(s_axi_wdata_mux), - .s_axi_wstrb(s_axi_wstrb_mux), - .s_axi_wlast(s_axi_wlast_mux), - .s_axi_wuser(s_axi_wuser_mux), - .s_axi_wvalid(s_axi_wvalid_mux), - .s_axi_wready(s_axi_wready_mux), - .s_axi_bid(int_m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH]), - .s_axi_bresp(int_m_axi_bresp[n*2 +: 2]), - .s_axi_buser(int_m_axi_buser[n*BUSER_WIDTH +: BUSER_WIDTH]), - .s_axi_bvalid(int_m_axi_bvalid[n]), - .s_axi_bready(int_m_axi_bready[n]), - .m_axi_awid(m_axi_awid[n*M_ID_WIDTH +: M_ID_WIDTH]), - .m_axi_awaddr(m_axi_awaddr[n*ADDR_WIDTH +: ADDR_WIDTH]), - .m_axi_awlen(m_axi_awlen[n*8 +: 8]), - .m_axi_awsize(m_axi_awsize[n*3 +: 3]), - .m_axi_awburst(m_axi_awburst[n*2 +: 2]), - .m_axi_awlock(m_axi_awlock[n]), - .m_axi_awcache(m_axi_awcache[n*4 +: 4]), - .m_axi_awprot(m_axi_awprot[n*3 +: 3]), - .m_axi_awqos(m_axi_awqos[n*4 +: 4]), - .m_axi_awregion(m_axi_awregion[n*4 +: 4]), - .m_axi_awuser(m_axi_awuser[n*AWUSER_WIDTH +: AWUSER_WIDTH]), - .m_axi_awvalid(m_axi_awvalid[n]), - .m_axi_awready(m_axi_awready[n]), - .m_axi_wdata(m_axi_wdata[n*DATA_WIDTH +: DATA_WIDTH]), - .m_axi_wstrb(m_axi_wstrb[n*STRB_WIDTH +: STRB_WIDTH]), - .m_axi_wlast(m_axi_wlast[n]), - .m_axi_wuser(m_axi_wuser[n*WUSER_WIDTH +: WUSER_WIDTH]), - .m_axi_wvalid(m_axi_wvalid[n]), - .m_axi_wready(m_axi_wready[n]), - .m_axi_bid(m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH]), - .m_axi_bresp(m_axi_bresp[n*2 +: 2]), - .m_axi_buser(m_axi_buser[n*BUSER_WIDTH +: BUSER_WIDTH]), - .m_axi_bvalid(m_axi_bvalid[n]), - .m_axi_bready(m_axi_bready[n]) - ); - end // m_ifaces - -endgenerate - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_crossbar_wrapper.v b/xls/modules/zstd/external/axi_crossbar_wrapper.v deleted file mode 100644 index 32c95071d0..0000000000 --- a/xls/modules/zstd/external/axi_crossbar_wrapper.v +++ /dev/null @@ -1,1246 +0,0 @@ -/* - -Copyright (c) 2020 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 15x1 crossbar (wrapper) - */ -module axi_crossbar_wrapper # -( - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Input ID field width (from AXI masters) - parameter S_ID_WIDTH = 8, - // Output ID field width (towards AXI slaves) - // Additional bits required for response routing - parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT), - // Propagate awuser signal - parameter AWUSER_ENABLE = 0, - // Width of awuser signal - parameter AWUSER_WIDTH = 1, - // Propagate wuser signal - parameter WUSER_ENABLE = 0, - // Width of wuser signal - parameter WUSER_WIDTH = 1, - // Propagate buser signal - parameter BUSER_ENABLE = 0, - // Width of buser signal - parameter BUSER_WIDTH = 1, - // Propagate aruser signal - parameter ARUSER_ENABLE = 0, - // Width of aruser signal - parameter ARUSER_WIDTH = 1, - // Propagate ruser signal - parameter RUSER_ENABLE = 0, - // Width of ruser signal - parameter RUSER_WIDTH = 1, - // Number of concurrent unique IDs - parameter S00_THREADS = 2, - // Number of concurrent operations - parameter S00_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S01_THREADS = 2, - // Number of concurrent operations - parameter S01_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S02_THREADS = 2, - // Number of concurrent operations - parameter S02_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S03_THREADS = 2, - // Number of concurrent operations - parameter S03_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S04_THREADS = 2, - // Number of concurrent operations - parameter S04_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S05_THREADS = 2, - // Number of concurrent operations - parameter S05_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S06_THREADS = 2, - // Number of concurrent operations - parameter S06_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S07_THREADS = 2, - // Number of concurrent operations - parameter S07_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S08_THREADS = 2, - // Number of concurrent operations - parameter S08_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S09_THREADS = 2, - // Number of concurrent operations - parameter S09_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S10_THREADS = 2, - // Number of concurrent operations - parameter S10_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S11_THREADS = 2, - // Number of concurrent operations - parameter S11_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S12_THREADS = 2, - // Number of concurrent operations - parameter S12_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S13_THREADS = 2, - // Number of concurrent operations - parameter S13_ACCEPT = 16, - // Number of concurrent unique IDs - parameter S14_THREADS = 2, - // Number of concurrent operations - parameter S14_ACCEPT = 16, - // Number of regions per master interface - parameter M_REGIONS = 1, - // Master interface base addresses - // M_REGIONS concatenated fields of ADDR_WIDTH bits - parameter M00_BASE_ADDR = 0, - // Master interface address widths - // M_REGIONS concatenated fields of 32 bits - parameter M00_ADDR_WIDTH = {M_REGIONS{32'd24}}, - // Read connections between interfaces - // S_COUNT bits - parameter M00_CONNECT_READ = 15'b111111111111111, - // Write connections between interfaces - // S_COUNT bits - parameter M00_CONNECT_WRITE = 15'b111111111111111, - // Number of concurrent operations for each master interface - parameter M00_ISSUE = 4, - // Secure master (fail operations based on awprot/arprot) - parameter M00_SECURE = 0, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S00_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S00_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S00_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S00_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S00_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S01_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S01_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S01_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S01_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S01_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S02_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S02_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S02_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S02_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S02_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S03_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S03_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S03_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S03_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S03_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S04_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S04_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S04_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S04_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S04_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S05_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S05_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S05_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S05_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S05_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S06_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S06_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S06_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S06_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S06_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S07_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S07_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S07_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S07_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S07_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S08_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S08_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S08_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S08_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S08_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S09_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S09_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S09_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S09_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S09_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S10_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S10_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S10_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S10_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S10_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S11_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S11_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S11_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S11_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S11_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S12_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S12_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S12_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S12_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S12_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S13_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S13_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S13_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S13_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S13_R_REG_TYPE = 2, - // Slave interface AW channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S14_AW_REG_TYPE = 0, - // Slave interface W channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S14_W_REG_TYPE = 0, - // Slave interface B channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S14_B_REG_TYPE = 1, - // Slave interface AR channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S14_AR_REG_TYPE = 0, - // Slave interface R channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter S14_R_REG_TYPE = 2, - // Master interface AW channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M00_AW_REG_TYPE = 1, - // Master interface W channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M00_W_REG_TYPE = 2, - // Master interface B channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M00_B_REG_TYPE = 0, - // Master interface AR channel register type (output) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M00_AR_REG_TYPE = 1, - // Master interface R channel register type (input) - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter M00_R_REG_TYPE = 0 -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interface - */ - input wire [S_ID_WIDTH-1:0] s00_axi_awid, - input wire [ADDR_WIDTH-1:0] s00_axi_awaddr, - input wire [7:0] s00_axi_awlen, - input wire [2:0] s00_axi_awsize, - input wire [1:0] s00_axi_awburst, - input wire s00_axi_awlock, - input wire [3:0] s00_axi_awcache, - input wire [2:0] s00_axi_awprot, - input wire [3:0] s00_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s00_axi_awuser, - input wire s00_axi_awvalid, - output wire s00_axi_awready, - input wire [DATA_WIDTH-1:0] s00_axi_wdata, - input wire [STRB_WIDTH-1:0] s00_axi_wstrb, - input wire s00_axi_wlast, - input wire [WUSER_WIDTH-1:0] s00_axi_wuser, - input wire s00_axi_wvalid, - output wire s00_axi_wready, - output wire [S_ID_WIDTH-1:0] s00_axi_bid, - output wire [1:0] s00_axi_bresp, - output wire [BUSER_WIDTH-1:0] s00_axi_buser, - output wire s00_axi_bvalid, - input wire s00_axi_bready, - input wire [S_ID_WIDTH-1:0] s00_axi_arid, - input wire [ADDR_WIDTH-1:0] s00_axi_araddr, - input wire [7:0] s00_axi_arlen, - input wire [2:0] s00_axi_arsize, - input wire [1:0] s00_axi_arburst, - input wire s00_axi_arlock, - input wire [3:0] s00_axi_arcache, - input wire [2:0] s00_axi_arprot, - input wire [3:0] s00_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s00_axi_aruser, - input wire s00_axi_arvalid, - output wire s00_axi_arready, - output wire [S_ID_WIDTH-1:0] s00_axi_rid, - output wire [DATA_WIDTH-1:0] s00_axi_rdata, - output wire [1:0] s00_axi_rresp, - output wire s00_axi_rlast, - output wire [RUSER_WIDTH-1:0] s00_axi_ruser, - output wire s00_axi_rvalid, - input wire s00_axi_rready, - - input wire [S_ID_WIDTH-1:0] s01_axi_awid, - input wire [ADDR_WIDTH-1:0] s01_axi_awaddr, - input wire [7:0] s01_axi_awlen, - input wire [2:0] s01_axi_awsize, - input wire [1:0] s01_axi_awburst, - input wire s01_axi_awlock, - input wire [3:0] s01_axi_awcache, - input wire [2:0] s01_axi_awprot, - input wire [3:0] s01_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s01_axi_awuser, - input wire s01_axi_awvalid, - output wire s01_axi_awready, - input wire [DATA_WIDTH-1:0] s01_axi_wdata, - input wire [STRB_WIDTH-1:0] s01_axi_wstrb, - input wire s01_axi_wlast, - input wire [WUSER_WIDTH-1:0] s01_axi_wuser, - input wire s01_axi_wvalid, - output wire s01_axi_wready, - output wire [S_ID_WIDTH-1:0] s01_axi_bid, - output wire [1:0] s01_axi_bresp, - output wire [BUSER_WIDTH-1:0] s01_axi_buser, - output wire s01_axi_bvalid, - input wire s01_axi_bready, - input wire [S_ID_WIDTH-1:0] s01_axi_arid, - input wire [ADDR_WIDTH-1:0] s01_axi_araddr, - input wire [7:0] s01_axi_arlen, - input wire [2:0] s01_axi_arsize, - input wire [1:0] s01_axi_arburst, - input wire s01_axi_arlock, - input wire [3:0] s01_axi_arcache, - input wire [2:0] s01_axi_arprot, - input wire [3:0] s01_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s01_axi_aruser, - input wire s01_axi_arvalid, - output wire s01_axi_arready, - output wire [S_ID_WIDTH-1:0] s01_axi_rid, - output wire [DATA_WIDTH-1:0] s01_axi_rdata, - output wire [1:0] s01_axi_rresp, - output wire s01_axi_rlast, - output wire [RUSER_WIDTH-1:0] s01_axi_ruser, - output wire s01_axi_rvalid, - input wire s01_axi_rready, - - input wire [S_ID_WIDTH-1:0] s02_axi_awid, - input wire [ADDR_WIDTH-1:0] s02_axi_awaddr, - input wire [7:0] s02_axi_awlen, - input wire [2:0] s02_axi_awsize, - input wire [1:0] s02_axi_awburst, - input wire s02_axi_awlock, - input wire [3:0] s02_axi_awcache, - input wire [2:0] s02_axi_awprot, - input wire [3:0] s02_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s02_axi_awuser, - input wire s02_axi_awvalid, - output wire s02_axi_awready, - input wire [DATA_WIDTH-1:0] s02_axi_wdata, - input wire [STRB_WIDTH-1:0] s02_axi_wstrb, - input wire s02_axi_wlast, - input wire [WUSER_WIDTH-1:0] s02_axi_wuser, - input wire s02_axi_wvalid, - output wire s02_axi_wready, - output wire [S_ID_WIDTH-1:0] s02_axi_bid, - output wire [1:0] s02_axi_bresp, - output wire [BUSER_WIDTH-1:0] s02_axi_buser, - output wire s02_axi_bvalid, - input wire s02_axi_bready, - input wire [S_ID_WIDTH-1:0] s02_axi_arid, - input wire [ADDR_WIDTH-1:0] s02_axi_araddr, - input wire [7:0] s02_axi_arlen, - input wire [2:0] s02_axi_arsize, - input wire [1:0] s02_axi_arburst, - input wire s02_axi_arlock, - input wire [3:0] s02_axi_arcache, - input wire [2:0] s02_axi_arprot, - input wire [3:0] s02_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s02_axi_aruser, - input wire s02_axi_arvalid, - output wire s02_axi_arready, - output wire [S_ID_WIDTH-1:0] s02_axi_rid, - output wire [DATA_WIDTH-1:0] s02_axi_rdata, - output wire [1:0] s02_axi_rresp, - output wire s02_axi_rlast, - output wire [RUSER_WIDTH-1:0] s02_axi_ruser, - output wire s02_axi_rvalid, - input wire s02_axi_rready, - - input wire [S_ID_WIDTH-1:0] s03_axi_awid, - input wire [ADDR_WIDTH-1:0] s03_axi_awaddr, - input wire [7:0] s03_axi_awlen, - input wire [2:0] s03_axi_awsize, - input wire [1:0] s03_axi_awburst, - input wire s03_axi_awlock, - input wire [3:0] s03_axi_awcache, - input wire [2:0] s03_axi_awprot, - input wire [3:0] s03_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s03_axi_awuser, - input wire s03_axi_awvalid, - output wire s03_axi_awready, - input wire [DATA_WIDTH-1:0] s03_axi_wdata, - input wire [STRB_WIDTH-1:0] s03_axi_wstrb, - input wire s03_axi_wlast, - input wire [WUSER_WIDTH-1:0] s03_axi_wuser, - input wire s03_axi_wvalid, - output wire s03_axi_wready, - output wire [S_ID_WIDTH-1:0] s03_axi_bid, - output wire [1:0] s03_axi_bresp, - output wire [BUSER_WIDTH-1:0] s03_axi_buser, - output wire s03_axi_bvalid, - input wire s03_axi_bready, - input wire [S_ID_WIDTH-1:0] s03_axi_arid, - input wire [ADDR_WIDTH-1:0] s03_axi_araddr, - input wire [7:0] s03_axi_arlen, - input wire [2:0] s03_axi_arsize, - input wire [1:0] s03_axi_arburst, - input wire s03_axi_arlock, - input wire [3:0] s03_axi_arcache, - input wire [2:0] s03_axi_arprot, - input wire [3:0] s03_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s03_axi_aruser, - input wire s03_axi_arvalid, - output wire s03_axi_arready, - output wire [S_ID_WIDTH-1:0] s03_axi_rid, - output wire [DATA_WIDTH-1:0] s03_axi_rdata, - output wire [1:0] s03_axi_rresp, - output wire s03_axi_rlast, - output wire [RUSER_WIDTH-1:0] s03_axi_ruser, - output wire s03_axi_rvalid, - input wire s03_axi_rready, - - input wire [S_ID_WIDTH-1:0] s04_axi_awid, - input wire [ADDR_WIDTH-1:0] s04_axi_awaddr, - input wire [7:0] s04_axi_awlen, - input wire [2:0] s04_axi_awsize, - input wire [1:0] s04_axi_awburst, - input wire s04_axi_awlock, - input wire [3:0] s04_axi_awcache, - input wire [2:0] s04_axi_awprot, - input wire [3:0] s04_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s04_axi_awuser, - input wire s04_axi_awvalid, - output wire s04_axi_awready, - input wire [DATA_WIDTH-1:0] s04_axi_wdata, - input wire [STRB_WIDTH-1:0] s04_axi_wstrb, - input wire s04_axi_wlast, - input wire [WUSER_WIDTH-1:0] s04_axi_wuser, - input wire s04_axi_wvalid, - output wire s04_axi_wready, - output wire [S_ID_WIDTH-1:0] s04_axi_bid, - output wire [1:0] s04_axi_bresp, - output wire [BUSER_WIDTH-1:0] s04_axi_buser, - output wire s04_axi_bvalid, - input wire s04_axi_bready, - input wire [S_ID_WIDTH-1:0] s04_axi_arid, - input wire [ADDR_WIDTH-1:0] s04_axi_araddr, - input wire [7:0] s04_axi_arlen, - input wire [2:0] s04_axi_arsize, - input wire [1:0] s04_axi_arburst, - input wire s04_axi_arlock, - input wire [3:0] s04_axi_arcache, - input wire [2:0] s04_axi_arprot, - input wire [3:0] s04_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s04_axi_aruser, - input wire s04_axi_arvalid, - output wire s04_axi_arready, - output wire [S_ID_WIDTH-1:0] s04_axi_rid, - output wire [DATA_WIDTH-1:0] s04_axi_rdata, - output wire [1:0] s04_axi_rresp, - output wire s04_axi_rlast, - output wire [RUSER_WIDTH-1:0] s04_axi_ruser, - output wire s04_axi_rvalid, - input wire s04_axi_rready, - - input wire [S_ID_WIDTH-1:0] s05_axi_awid, - input wire [ADDR_WIDTH-1:0] s05_axi_awaddr, - input wire [7:0] s05_axi_awlen, - input wire [2:0] s05_axi_awsize, - input wire [1:0] s05_axi_awburst, - input wire s05_axi_awlock, - input wire [3:0] s05_axi_awcache, - input wire [2:0] s05_axi_awprot, - input wire [3:0] s05_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s05_axi_awuser, - input wire s05_axi_awvalid, - output wire s05_axi_awready, - input wire [DATA_WIDTH-1:0] s05_axi_wdata, - input wire [STRB_WIDTH-1:0] s05_axi_wstrb, - input wire s05_axi_wlast, - input wire [WUSER_WIDTH-1:0] s05_axi_wuser, - input wire s05_axi_wvalid, - output wire s05_axi_wready, - output wire [S_ID_WIDTH-1:0] s05_axi_bid, - output wire [1:0] s05_axi_bresp, - output wire [BUSER_WIDTH-1:0] s05_axi_buser, - output wire s05_axi_bvalid, - input wire s05_axi_bready, - input wire [S_ID_WIDTH-1:0] s05_axi_arid, - input wire [ADDR_WIDTH-1:0] s05_axi_araddr, - input wire [7:0] s05_axi_arlen, - input wire [2:0] s05_axi_arsize, - input wire [1:0] s05_axi_arburst, - input wire s05_axi_arlock, - input wire [3:0] s05_axi_arcache, - input wire [2:0] s05_axi_arprot, - input wire [3:0] s05_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s05_axi_aruser, - input wire s05_axi_arvalid, - output wire s05_axi_arready, - output wire [S_ID_WIDTH-1:0] s05_axi_rid, - output wire [DATA_WIDTH-1:0] s05_axi_rdata, - output wire [1:0] s05_axi_rresp, - output wire s05_axi_rlast, - output wire [RUSER_WIDTH-1:0] s05_axi_ruser, - output wire s05_axi_rvalid, - input wire s05_axi_rready, - - input wire [S_ID_WIDTH-1:0] s06_axi_awid, - input wire [ADDR_WIDTH-1:0] s06_axi_awaddr, - input wire [7:0] s06_axi_awlen, - input wire [2:0] s06_axi_awsize, - input wire [1:0] s06_axi_awburst, - input wire s06_axi_awlock, - input wire [3:0] s06_axi_awcache, - input wire [2:0] s06_axi_awprot, - input wire [3:0] s06_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s06_axi_awuser, - input wire s06_axi_awvalid, - output wire s06_axi_awready, - input wire [DATA_WIDTH-1:0] s06_axi_wdata, - input wire [STRB_WIDTH-1:0] s06_axi_wstrb, - input wire s06_axi_wlast, - input wire [WUSER_WIDTH-1:0] s06_axi_wuser, - input wire s06_axi_wvalid, - output wire s06_axi_wready, - output wire [S_ID_WIDTH-1:0] s06_axi_bid, - output wire [1:0] s06_axi_bresp, - output wire [BUSER_WIDTH-1:0] s06_axi_buser, - output wire s06_axi_bvalid, - input wire s06_axi_bready, - input wire [S_ID_WIDTH-1:0] s06_axi_arid, - input wire [ADDR_WIDTH-1:0] s06_axi_araddr, - input wire [7:0] s06_axi_arlen, - input wire [2:0] s06_axi_arsize, - input wire [1:0] s06_axi_arburst, - input wire s06_axi_arlock, - input wire [3:0] s06_axi_arcache, - input wire [2:0] s06_axi_arprot, - input wire [3:0] s06_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s06_axi_aruser, - input wire s06_axi_arvalid, - output wire s06_axi_arready, - output wire [S_ID_WIDTH-1:0] s06_axi_rid, - output wire [DATA_WIDTH-1:0] s06_axi_rdata, - output wire [1:0] s06_axi_rresp, - output wire s06_axi_rlast, - output wire [RUSER_WIDTH-1:0] s06_axi_ruser, - output wire s06_axi_rvalid, - input wire s06_axi_rready, - - input wire [S_ID_WIDTH-1:0] s07_axi_awid, - input wire [ADDR_WIDTH-1:0] s07_axi_awaddr, - input wire [7:0] s07_axi_awlen, - input wire [2:0] s07_axi_awsize, - input wire [1:0] s07_axi_awburst, - input wire s07_axi_awlock, - input wire [3:0] s07_axi_awcache, - input wire [2:0] s07_axi_awprot, - input wire [3:0] s07_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s07_axi_awuser, - input wire s07_axi_awvalid, - output wire s07_axi_awready, - input wire [DATA_WIDTH-1:0] s07_axi_wdata, - input wire [STRB_WIDTH-1:0] s07_axi_wstrb, - input wire s07_axi_wlast, - input wire [WUSER_WIDTH-1:0] s07_axi_wuser, - input wire s07_axi_wvalid, - output wire s07_axi_wready, - output wire [S_ID_WIDTH-1:0] s07_axi_bid, - output wire [1:0] s07_axi_bresp, - output wire [BUSER_WIDTH-1:0] s07_axi_buser, - output wire s07_axi_bvalid, - input wire s07_axi_bready, - input wire [S_ID_WIDTH-1:0] s07_axi_arid, - input wire [ADDR_WIDTH-1:0] s07_axi_araddr, - input wire [7:0] s07_axi_arlen, - input wire [2:0] s07_axi_arsize, - input wire [1:0] s07_axi_arburst, - input wire s07_axi_arlock, - input wire [3:0] s07_axi_arcache, - input wire [2:0] s07_axi_arprot, - input wire [3:0] s07_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s07_axi_aruser, - input wire s07_axi_arvalid, - output wire s07_axi_arready, - output wire [S_ID_WIDTH-1:0] s07_axi_rid, - output wire [DATA_WIDTH-1:0] s07_axi_rdata, - output wire [1:0] s07_axi_rresp, - output wire s07_axi_rlast, - output wire [RUSER_WIDTH-1:0] s07_axi_ruser, - output wire s07_axi_rvalid, - input wire s07_axi_rready, - - input wire [S_ID_WIDTH-1:0] s08_axi_awid, - input wire [ADDR_WIDTH-1:0] s08_axi_awaddr, - input wire [7:0] s08_axi_awlen, - input wire [2:0] s08_axi_awsize, - input wire [1:0] s08_axi_awburst, - input wire s08_axi_awlock, - input wire [3:0] s08_axi_awcache, - input wire [2:0] s08_axi_awprot, - input wire [3:0] s08_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s08_axi_awuser, - input wire s08_axi_awvalid, - output wire s08_axi_awready, - input wire [DATA_WIDTH-1:0] s08_axi_wdata, - input wire [STRB_WIDTH-1:0] s08_axi_wstrb, - input wire s08_axi_wlast, - input wire [WUSER_WIDTH-1:0] s08_axi_wuser, - input wire s08_axi_wvalid, - output wire s08_axi_wready, - output wire [S_ID_WIDTH-1:0] s08_axi_bid, - output wire [1:0] s08_axi_bresp, - output wire [BUSER_WIDTH-1:0] s08_axi_buser, - output wire s08_axi_bvalid, - input wire s08_axi_bready, - input wire [S_ID_WIDTH-1:0] s08_axi_arid, - input wire [ADDR_WIDTH-1:0] s08_axi_araddr, - input wire [7:0] s08_axi_arlen, - input wire [2:0] s08_axi_arsize, - input wire [1:0] s08_axi_arburst, - input wire s08_axi_arlock, - input wire [3:0] s08_axi_arcache, - input wire [2:0] s08_axi_arprot, - input wire [3:0] s08_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s08_axi_aruser, - input wire s08_axi_arvalid, - output wire s08_axi_arready, - output wire [S_ID_WIDTH-1:0] s08_axi_rid, - output wire [DATA_WIDTH-1:0] s08_axi_rdata, - output wire [1:0] s08_axi_rresp, - output wire s08_axi_rlast, - output wire [RUSER_WIDTH-1:0] s08_axi_ruser, - output wire s08_axi_rvalid, - input wire s08_axi_rready, - - input wire [S_ID_WIDTH-1:0] s09_axi_awid, - input wire [ADDR_WIDTH-1:0] s09_axi_awaddr, - input wire [7:0] s09_axi_awlen, - input wire [2:0] s09_axi_awsize, - input wire [1:0] s09_axi_awburst, - input wire s09_axi_awlock, - input wire [3:0] s09_axi_awcache, - input wire [2:0] s09_axi_awprot, - input wire [3:0] s09_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s09_axi_awuser, - input wire s09_axi_awvalid, - output wire s09_axi_awready, - input wire [DATA_WIDTH-1:0] s09_axi_wdata, - input wire [STRB_WIDTH-1:0] s09_axi_wstrb, - input wire s09_axi_wlast, - input wire [WUSER_WIDTH-1:0] s09_axi_wuser, - input wire s09_axi_wvalid, - output wire s09_axi_wready, - output wire [S_ID_WIDTH-1:0] s09_axi_bid, - output wire [1:0] s09_axi_bresp, - output wire [BUSER_WIDTH-1:0] s09_axi_buser, - output wire s09_axi_bvalid, - input wire s09_axi_bready, - input wire [S_ID_WIDTH-1:0] s09_axi_arid, - input wire [ADDR_WIDTH-1:0] s09_axi_araddr, - input wire [7:0] s09_axi_arlen, - input wire [2:0] s09_axi_arsize, - input wire [1:0] s09_axi_arburst, - input wire s09_axi_arlock, - input wire [3:0] s09_axi_arcache, - input wire [2:0] s09_axi_arprot, - input wire [3:0] s09_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s09_axi_aruser, - input wire s09_axi_arvalid, - output wire s09_axi_arready, - output wire [S_ID_WIDTH-1:0] s09_axi_rid, - output wire [DATA_WIDTH-1:0] s09_axi_rdata, - output wire [1:0] s09_axi_rresp, - output wire s09_axi_rlast, - output wire [RUSER_WIDTH-1:0] s09_axi_ruser, - output wire s09_axi_rvalid, - input wire s09_axi_rready, - - input wire [S_ID_WIDTH-1:0] s10_axi_awid, - input wire [ADDR_WIDTH-1:0] s10_axi_awaddr, - input wire [7:0] s10_axi_awlen, - input wire [2:0] s10_axi_awsize, - input wire [1:0] s10_axi_awburst, - input wire s10_axi_awlock, - input wire [3:0] s10_axi_awcache, - input wire [2:0] s10_axi_awprot, - input wire [3:0] s10_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s10_axi_awuser, - input wire s10_axi_awvalid, - output wire s10_axi_awready, - input wire [DATA_WIDTH-1:0] s10_axi_wdata, - input wire [STRB_WIDTH-1:0] s10_axi_wstrb, - input wire s10_axi_wlast, - input wire [WUSER_WIDTH-1:0] s10_axi_wuser, - input wire s10_axi_wvalid, - output wire s10_axi_wready, - output wire [S_ID_WIDTH-1:0] s10_axi_bid, - output wire [1:0] s10_axi_bresp, - output wire [BUSER_WIDTH-1:0] s10_axi_buser, - output wire s10_axi_bvalid, - input wire s10_axi_bready, - input wire [S_ID_WIDTH-1:0] s10_axi_arid, - input wire [ADDR_WIDTH-1:0] s10_axi_araddr, - input wire [7:0] s10_axi_arlen, - input wire [2:0] s10_axi_arsize, - input wire [1:0] s10_axi_arburst, - input wire s10_axi_arlock, - input wire [3:0] s10_axi_arcache, - input wire [2:0] s10_axi_arprot, - input wire [3:0] s10_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s10_axi_aruser, - input wire s10_axi_arvalid, - output wire s10_axi_arready, - output wire [S_ID_WIDTH-1:0] s10_axi_rid, - output wire [DATA_WIDTH-1:0] s10_axi_rdata, - output wire [1:0] s10_axi_rresp, - output wire s10_axi_rlast, - output wire [RUSER_WIDTH-1:0] s10_axi_ruser, - output wire s10_axi_rvalid, - input wire s10_axi_rready, - - input wire [S_ID_WIDTH-1:0] s11_axi_awid, - input wire [ADDR_WIDTH-1:0] s11_axi_awaddr, - input wire [7:0] s11_axi_awlen, - input wire [2:0] s11_axi_awsize, - input wire [1:0] s11_axi_awburst, - input wire s11_axi_awlock, - input wire [3:0] s11_axi_awcache, - input wire [2:0] s11_axi_awprot, - input wire [3:0] s11_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s11_axi_awuser, - input wire s11_axi_awvalid, - output wire s11_axi_awready, - input wire [DATA_WIDTH-1:0] s11_axi_wdata, - input wire [STRB_WIDTH-1:0] s11_axi_wstrb, - input wire s11_axi_wlast, - input wire [WUSER_WIDTH-1:0] s11_axi_wuser, - input wire s11_axi_wvalid, - output wire s11_axi_wready, - output wire [S_ID_WIDTH-1:0] s11_axi_bid, - output wire [1:0] s11_axi_bresp, - output wire [BUSER_WIDTH-1:0] s11_axi_buser, - output wire s11_axi_bvalid, - input wire s11_axi_bready, - input wire [S_ID_WIDTH-1:0] s11_axi_arid, - input wire [ADDR_WIDTH-1:0] s11_axi_araddr, - input wire [7:0] s11_axi_arlen, - input wire [2:0] s11_axi_arsize, - input wire [1:0] s11_axi_arburst, - input wire s11_axi_arlock, - input wire [3:0] s11_axi_arcache, - input wire [2:0] s11_axi_arprot, - input wire [3:0] s11_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s11_axi_aruser, - input wire s11_axi_arvalid, - output wire s11_axi_arready, - output wire [S_ID_WIDTH-1:0] s11_axi_rid, - output wire [DATA_WIDTH-1:0] s11_axi_rdata, - output wire [1:0] s11_axi_rresp, - output wire s11_axi_rlast, - output wire [RUSER_WIDTH-1:0] s11_axi_ruser, - output wire s11_axi_rvalid, - input wire s11_axi_rready, - - input wire [S_ID_WIDTH-1:0] s12_axi_awid, - input wire [ADDR_WIDTH-1:0] s12_axi_awaddr, - input wire [7:0] s12_axi_awlen, - input wire [2:0] s12_axi_awsize, - input wire [1:0] s12_axi_awburst, - input wire s12_axi_awlock, - input wire [3:0] s12_axi_awcache, - input wire [2:0] s12_axi_awprot, - input wire [3:0] s12_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s12_axi_awuser, - input wire s12_axi_awvalid, - output wire s12_axi_awready, - input wire [DATA_WIDTH-1:0] s12_axi_wdata, - input wire [STRB_WIDTH-1:0] s12_axi_wstrb, - input wire s12_axi_wlast, - input wire [WUSER_WIDTH-1:0] s12_axi_wuser, - input wire s12_axi_wvalid, - output wire s12_axi_wready, - output wire [S_ID_WIDTH-1:0] s12_axi_bid, - output wire [1:0] s12_axi_bresp, - output wire [BUSER_WIDTH-1:0] s12_axi_buser, - output wire s12_axi_bvalid, - input wire s12_axi_bready, - input wire [S_ID_WIDTH-1:0] s12_axi_arid, - input wire [ADDR_WIDTH-1:0] s12_axi_araddr, - input wire [7:0] s12_axi_arlen, - input wire [2:0] s12_axi_arsize, - input wire [1:0] s12_axi_arburst, - input wire s12_axi_arlock, - input wire [3:0] s12_axi_arcache, - input wire [2:0] s12_axi_arprot, - input wire [3:0] s12_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s12_axi_aruser, - input wire s12_axi_arvalid, - output wire s12_axi_arready, - output wire [S_ID_WIDTH-1:0] s12_axi_rid, - output wire [DATA_WIDTH-1:0] s12_axi_rdata, - output wire [1:0] s12_axi_rresp, - output wire s12_axi_rlast, - output wire [RUSER_WIDTH-1:0] s12_axi_ruser, - output wire s12_axi_rvalid, - input wire s12_axi_rready, - - input wire [S_ID_WIDTH-1:0] s13_axi_awid, - input wire [ADDR_WIDTH-1:0] s13_axi_awaddr, - input wire [7:0] s13_axi_awlen, - input wire [2:0] s13_axi_awsize, - input wire [1:0] s13_axi_awburst, - input wire s13_axi_awlock, - input wire [3:0] s13_axi_awcache, - input wire [2:0] s13_axi_awprot, - input wire [3:0] s13_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s13_axi_awuser, - input wire s13_axi_awvalid, - output wire s13_axi_awready, - input wire [DATA_WIDTH-1:0] s13_axi_wdata, - input wire [STRB_WIDTH-1:0] s13_axi_wstrb, - input wire s13_axi_wlast, - input wire [WUSER_WIDTH-1:0] s13_axi_wuser, - input wire s13_axi_wvalid, - output wire s13_axi_wready, - output wire [S_ID_WIDTH-1:0] s13_axi_bid, - output wire [1:0] s13_axi_bresp, - output wire [BUSER_WIDTH-1:0] s13_axi_buser, - output wire s13_axi_bvalid, - input wire s13_axi_bready, - input wire [S_ID_WIDTH-1:0] s13_axi_arid, - input wire [ADDR_WIDTH-1:0] s13_axi_araddr, - input wire [7:0] s13_axi_arlen, - input wire [2:0] s13_axi_arsize, - input wire [1:0] s13_axi_arburst, - input wire s13_axi_arlock, - input wire [3:0] s13_axi_arcache, - input wire [2:0] s13_axi_arprot, - input wire [3:0] s13_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s13_axi_aruser, - input wire s13_axi_arvalid, - output wire s13_axi_arready, - output wire [S_ID_WIDTH-1:0] s13_axi_rid, - output wire [DATA_WIDTH-1:0] s13_axi_rdata, - output wire [1:0] s13_axi_rresp, - output wire s13_axi_rlast, - output wire [RUSER_WIDTH-1:0] s13_axi_ruser, - output wire s13_axi_rvalid, - input wire s13_axi_rready, - - input wire [S_ID_WIDTH-1:0] s14_axi_awid, - input wire [ADDR_WIDTH-1:0] s14_axi_awaddr, - input wire [7:0] s14_axi_awlen, - input wire [2:0] s14_axi_awsize, - input wire [1:0] s14_axi_awburst, - input wire s14_axi_awlock, - input wire [3:0] s14_axi_awcache, - input wire [2:0] s14_axi_awprot, - input wire [3:0] s14_axi_awqos, - input wire [AWUSER_WIDTH-1:0] s14_axi_awuser, - input wire s14_axi_awvalid, - output wire s14_axi_awready, - input wire [DATA_WIDTH-1:0] s14_axi_wdata, - input wire [STRB_WIDTH-1:0] s14_axi_wstrb, - input wire s14_axi_wlast, - input wire [WUSER_WIDTH-1:0] s14_axi_wuser, - input wire s14_axi_wvalid, - output wire s14_axi_wready, - output wire [S_ID_WIDTH-1:0] s14_axi_bid, - output wire [1:0] s14_axi_bresp, - output wire [BUSER_WIDTH-1:0] s14_axi_buser, - output wire s14_axi_bvalid, - input wire s14_axi_bready, - input wire [S_ID_WIDTH-1:0] s14_axi_arid, - input wire [ADDR_WIDTH-1:0] s14_axi_araddr, - input wire [7:0] s14_axi_arlen, - input wire [2:0] s14_axi_arsize, - input wire [1:0] s14_axi_arburst, - input wire s14_axi_arlock, - input wire [3:0] s14_axi_arcache, - input wire [2:0] s14_axi_arprot, - input wire [3:0] s14_axi_arqos, - input wire [ARUSER_WIDTH-1:0] s14_axi_aruser, - input wire s14_axi_arvalid, - output wire s14_axi_arready, - output wire [S_ID_WIDTH-1:0] s14_axi_rid, - output wire [DATA_WIDTH-1:0] s14_axi_rdata, - output wire [1:0] s14_axi_rresp, - output wire s14_axi_rlast, - output wire [RUSER_WIDTH-1:0] s14_axi_ruser, - output wire s14_axi_rvalid, - input wire s14_axi_rready, - - /* - * AXI master interface - */ - output wire [M_ID_WIDTH-1:0] m00_axi_awid, - output wire [ADDR_WIDTH-1:0] m00_axi_awaddr, - output wire [7:0] m00_axi_awlen, - output wire [2:0] m00_axi_awsize, - output wire [1:0] m00_axi_awburst, - output wire m00_axi_awlock, - output wire [3:0] m00_axi_awcache, - output wire [2:0] m00_axi_awprot, - output wire [3:0] m00_axi_awqos, - output wire [3:0] m00_axi_awregion, - output wire [AWUSER_WIDTH-1:0] m00_axi_awuser, - output wire m00_axi_awvalid, - input wire m00_axi_awready, - output wire [DATA_WIDTH-1:0] m00_axi_wdata, - output wire [STRB_WIDTH-1:0] m00_axi_wstrb, - output wire m00_axi_wlast, - output wire [WUSER_WIDTH-1:0] m00_axi_wuser, - output wire m00_axi_wvalid, - input wire m00_axi_wready, - input wire [M_ID_WIDTH-1:0] m00_axi_bid, - input wire [1:0] m00_axi_bresp, - input wire [BUSER_WIDTH-1:0] m00_axi_buser, - input wire m00_axi_bvalid, - output wire m00_axi_bready, - output wire [M_ID_WIDTH-1:0] m00_axi_arid, - output wire [ADDR_WIDTH-1:0] m00_axi_araddr, - output wire [7:0] m00_axi_arlen, - output wire [2:0] m00_axi_arsize, - output wire [1:0] m00_axi_arburst, - output wire m00_axi_arlock, - output wire [3:0] m00_axi_arcache, - output wire [2:0] m00_axi_arprot, - output wire [3:0] m00_axi_arqos, - output wire [3:0] m00_axi_arregion, - output wire [ARUSER_WIDTH-1:0] m00_axi_aruser, - output wire m00_axi_arvalid, - input wire m00_axi_arready, - input wire [M_ID_WIDTH-1:0] m00_axi_rid, - input wire [DATA_WIDTH-1:0] m00_axi_rdata, - input wire [1:0] m00_axi_rresp, - input wire m00_axi_rlast, - input wire [RUSER_WIDTH-1:0] m00_axi_ruser, - input wire m00_axi_rvalid, - output wire m00_axi_rready -); - -localparam S_COUNT = 15; -localparam M_COUNT = 1; - -// parameter sizing helpers -function [ADDR_WIDTH*M_REGIONS-1:0] w_a_r(input [ADDR_WIDTH*M_REGIONS-1:0] val); - w_a_r = val; -endfunction - -function [32*M_REGIONS-1:0] w_32_r(input [32*M_REGIONS-1:0] val); - w_32_r = val; -endfunction - -function [S_COUNT-1:0] w_s(input [S_COUNT-1:0] val); - w_s = val; -endfunction - -function [31:0] w_32(input [31:0] val); - w_32 = val; -endfunction - -function [1:0] w_2(input [1:0] val); - w_2 = val; -endfunction - -function w_1(input val); - w_1 = val; -endfunction - -axi_crossbar #( - .S_COUNT(S_COUNT), - .M_COUNT(M_COUNT), - .DATA_WIDTH(DATA_WIDTH), - .ADDR_WIDTH(ADDR_WIDTH), - .STRB_WIDTH(STRB_WIDTH), - .S_ID_WIDTH(S_ID_WIDTH), - .M_ID_WIDTH(M_ID_WIDTH), - .AWUSER_ENABLE(AWUSER_ENABLE), - .AWUSER_WIDTH(AWUSER_WIDTH), - .WUSER_ENABLE(WUSER_ENABLE), - .WUSER_WIDTH(WUSER_WIDTH), - .BUSER_ENABLE(BUSER_ENABLE), - .BUSER_WIDTH(BUSER_WIDTH), - .ARUSER_ENABLE(ARUSER_ENABLE), - .ARUSER_WIDTH(ARUSER_WIDTH), - .RUSER_ENABLE(RUSER_ENABLE), - .RUSER_WIDTH(RUSER_WIDTH), - .S_THREADS({ w_32(S14_THREADS), w_32(S13_THREADS), w_32(S12_THREADS), w_32(S11_THREADS), w_32(S10_THREADS), w_32(S09_THREADS), w_32(S08_THREADS), w_32(S07_THREADS), w_32(S06_THREADS), w_32(S05_THREADS), w_32(S04_THREADS), w_32(S03_THREADS), w_32(S02_THREADS), w_32(S01_THREADS), w_32(S00_THREADS) }), - .S_ACCEPT({ w_32(S14_ACCEPT), w_32(S13_ACCEPT), w_32(S12_ACCEPT), w_32(S11_ACCEPT), w_32(S10_ACCEPT), w_32(S09_ACCEPT), w_32(S08_ACCEPT), w_32(S07_ACCEPT), w_32(S06_ACCEPT), w_32(S05_ACCEPT), w_32(S04_ACCEPT), w_32(S03_ACCEPT), w_32(S02_ACCEPT), w_32(S01_ACCEPT), w_32(S00_ACCEPT) }), - .M_REGIONS(M_REGIONS), - .M_BASE_ADDR({ w_a_r(M00_BASE_ADDR) }), - .M_ADDR_WIDTH({ w_32_r(M00_ADDR_WIDTH) }), - .M_CONNECT_READ({ w_s(M00_CONNECT_READ) }), - .M_CONNECT_WRITE({ w_s(M00_CONNECT_WRITE) }), - .M_ISSUE({ w_32(M00_ISSUE) }), - .M_SECURE({ w_1(M00_SECURE) }), - .S_AR_REG_TYPE({ w_2(S14_AR_REG_TYPE), w_2(S13_AR_REG_TYPE), w_2(S12_AR_REG_TYPE), w_2(S11_AR_REG_TYPE), w_2(S10_AR_REG_TYPE), w_2(S09_AR_REG_TYPE), w_2(S08_AR_REG_TYPE), w_2(S07_AR_REG_TYPE), w_2(S06_AR_REG_TYPE), w_2(S05_AR_REG_TYPE), w_2(S04_AR_REG_TYPE), w_2(S03_AR_REG_TYPE), w_2(S02_AR_REG_TYPE), w_2(S01_AR_REG_TYPE), w_2(S00_AR_REG_TYPE) }), - .S_R_REG_TYPE({ w_2(S14_R_REG_TYPE), w_2(S13_R_REG_TYPE), w_2(S12_R_REG_TYPE), w_2(S11_R_REG_TYPE), w_2(S10_R_REG_TYPE), w_2(S09_R_REG_TYPE), w_2(S08_R_REG_TYPE), w_2(S07_R_REG_TYPE), w_2(S06_R_REG_TYPE), w_2(S05_R_REG_TYPE), w_2(S04_R_REG_TYPE), w_2(S03_R_REG_TYPE), w_2(S02_R_REG_TYPE), w_2(S01_R_REG_TYPE), w_2(S00_R_REG_TYPE) }), - .S_AW_REG_TYPE({ w_2(S14_AW_REG_TYPE), w_2(S13_AW_REG_TYPE), w_2(S12_AW_REG_TYPE), w_2(S11_AW_REG_TYPE), w_2(S10_AW_REG_TYPE), w_2(S09_AW_REG_TYPE), w_2(S08_AW_REG_TYPE), w_2(S07_AW_REG_TYPE), w_2(S06_AW_REG_TYPE), w_2(S05_AW_REG_TYPE), w_2(S04_AW_REG_TYPE), w_2(S03_AW_REG_TYPE), w_2(S02_AW_REG_TYPE), w_2(S01_AW_REG_TYPE), w_2(S00_AW_REG_TYPE) }), - .S_W_REG_TYPE({ w_2(S14_W_REG_TYPE), w_2(S13_W_REG_TYPE), w_2(S12_W_REG_TYPE), w_2(S11_W_REG_TYPE), w_2(S10_W_REG_TYPE), w_2(S09_W_REG_TYPE), w_2(S08_W_REG_TYPE), w_2(S07_W_REG_TYPE), w_2(S06_W_REG_TYPE), w_2(S05_W_REG_TYPE), w_2(S04_W_REG_TYPE), w_2(S03_W_REG_TYPE), w_2(S02_W_REG_TYPE), w_2(S01_W_REG_TYPE), w_2(S00_W_REG_TYPE) }), - .S_B_REG_TYPE({ w_2(S14_B_REG_TYPE), w_2(S13_B_REG_TYPE), w_2(S12_B_REG_TYPE), w_2(S11_B_REG_TYPE), w_2(S10_B_REG_TYPE), w_2(S09_B_REG_TYPE), w_2(S08_B_REG_TYPE), w_2(S07_B_REG_TYPE), w_2(S06_B_REG_TYPE), w_2(S05_B_REG_TYPE), w_2(S04_B_REG_TYPE), w_2(S03_B_REG_TYPE), w_2(S02_B_REG_TYPE), w_2(S01_B_REG_TYPE), w_2(S00_B_REG_TYPE) }), - .M_AR_REG_TYPE({ w_2(M00_AR_REG_TYPE) }), - .M_R_REG_TYPE({ w_2(M00_R_REG_TYPE) }), - .M_AW_REG_TYPE({ w_2(M00_AW_REG_TYPE) }), - .M_W_REG_TYPE({ w_2(M00_W_REG_TYPE) }), - .M_B_REG_TYPE({ w_2(M00_B_REG_TYPE) }) -) -axi_crossbar_inst ( - .clk(clk), - .rst(rst), - .s_axi_awid({ s14_axi_awid, s13_axi_awid, s12_axi_awid, s11_axi_awid, s10_axi_awid, s09_axi_awid, s08_axi_awid, s07_axi_awid, s06_axi_awid, s05_axi_awid, s04_axi_awid, s03_axi_awid, s02_axi_awid, s01_axi_awid, s00_axi_awid }), - .s_axi_awaddr({ s14_axi_awaddr, s13_axi_awaddr, s12_axi_awaddr, s11_axi_awaddr, s10_axi_awaddr, s09_axi_awaddr, s08_axi_awaddr, s07_axi_awaddr, s06_axi_awaddr, s05_axi_awaddr, s04_axi_awaddr, s03_axi_awaddr, s02_axi_awaddr, s01_axi_awaddr, s00_axi_awaddr }), - .s_axi_awlen({ s14_axi_awlen, s13_axi_awlen, s12_axi_awlen, s11_axi_awlen, s10_axi_awlen, s09_axi_awlen, s08_axi_awlen, s07_axi_awlen, s06_axi_awlen, s05_axi_awlen, s04_axi_awlen, s03_axi_awlen, s02_axi_awlen, s01_axi_awlen, s00_axi_awlen }), - .s_axi_awsize({ s14_axi_awsize, s13_axi_awsize, s12_axi_awsize, s11_axi_awsize, s10_axi_awsize, s09_axi_awsize, s08_axi_awsize, s07_axi_awsize, s06_axi_awsize, s05_axi_awsize, s04_axi_awsize, s03_axi_awsize, s02_axi_awsize, s01_axi_awsize, s00_axi_awsize }), - .s_axi_awburst({ s14_axi_awburst, s13_axi_awburst, s12_axi_awburst, s11_axi_awburst, s10_axi_awburst, s09_axi_awburst, s08_axi_awburst, s07_axi_awburst, s06_axi_awburst, s05_axi_awburst, s04_axi_awburst, s03_axi_awburst, s02_axi_awburst, s01_axi_awburst, s00_axi_awburst }), - .s_axi_awlock({ s14_axi_awlock, s13_axi_awlock, s12_axi_awlock, s11_axi_awlock, s10_axi_awlock, s09_axi_awlock, s08_axi_awlock, s07_axi_awlock, s06_axi_awlock, s05_axi_awlock, s04_axi_awlock, s03_axi_awlock, s02_axi_awlock, s01_axi_awlock, s00_axi_awlock }), - .s_axi_awcache({ s14_axi_awcache, s13_axi_awcache, s12_axi_awcache, s11_axi_awcache, s10_axi_awcache, s09_axi_awcache, s08_axi_awcache, s07_axi_awcache, s06_axi_awcache, s05_axi_awcache, s04_axi_awcache, s03_axi_awcache, s02_axi_awcache, s01_axi_awcache, s00_axi_awcache }), - .s_axi_awprot({ s14_axi_awprot, s13_axi_awprot, s12_axi_awprot, s11_axi_awprot, s10_axi_awprot, s09_axi_awprot, s08_axi_awprot, s07_axi_awprot, s06_axi_awprot, s05_axi_awprot, s04_axi_awprot, s03_axi_awprot, s02_axi_awprot, s01_axi_awprot, s00_axi_awprot }), - .s_axi_awqos({ s14_axi_awqos, s13_axi_awqos, s12_axi_awqos, s11_axi_awqos, s10_axi_awqos, s09_axi_awqos, s08_axi_awqos, s07_axi_awqos, s06_axi_awqos, s05_axi_awqos, s04_axi_awqos, s03_axi_awqos, s02_axi_awqos, s01_axi_awqos, s00_axi_awqos }), - .s_axi_awuser({ s14_axi_awuser, s13_axi_awuser, s12_axi_awuser, s11_axi_awuser, s10_axi_awuser, s09_axi_awuser, s08_axi_awuser, s07_axi_awuser, s06_axi_awuser, s05_axi_awuser, s04_axi_awuser, s03_axi_awuser, s02_axi_awuser, s01_axi_awuser, s00_axi_awuser }), - .s_axi_awvalid({ s14_axi_awvalid, s13_axi_awvalid, s12_axi_awvalid, s11_axi_awvalid, s10_axi_awvalid, s09_axi_awvalid, s08_axi_awvalid, s07_axi_awvalid, s06_axi_awvalid, s05_axi_awvalid, s04_axi_awvalid, s03_axi_awvalid, s02_axi_awvalid, s01_axi_awvalid, s00_axi_awvalid }), - .s_axi_awready({ s14_axi_awready, s13_axi_awready, s12_axi_awready, s11_axi_awready, s10_axi_awready, s09_axi_awready, s08_axi_awready, s07_axi_awready, s06_axi_awready, s05_axi_awready, s04_axi_awready, s03_axi_awready, s02_axi_awready, s01_axi_awready, s00_axi_awready }), - .s_axi_wdata({ s14_axi_wdata, s13_axi_wdata, s12_axi_wdata, s11_axi_wdata, s10_axi_wdata, s09_axi_wdata, s08_axi_wdata, s07_axi_wdata, s06_axi_wdata, s05_axi_wdata, s04_axi_wdata, s03_axi_wdata, s02_axi_wdata, s01_axi_wdata, s00_axi_wdata }), - .s_axi_wstrb({ s14_axi_wstrb, s13_axi_wstrb, s12_axi_wstrb, s11_axi_wstrb, s10_axi_wstrb, s09_axi_wstrb, s08_axi_wstrb, s07_axi_wstrb, s06_axi_wstrb, s05_axi_wstrb, s04_axi_wstrb, s03_axi_wstrb, s02_axi_wstrb, s01_axi_wstrb, s00_axi_wstrb }), - .s_axi_wlast({ s14_axi_wlast, s13_axi_wlast, s12_axi_wlast, s11_axi_wlast, s10_axi_wlast, s09_axi_wlast, s08_axi_wlast, s07_axi_wlast, s06_axi_wlast, s05_axi_wlast, s04_axi_wlast, s03_axi_wlast, s02_axi_wlast, s01_axi_wlast, s00_axi_wlast }), - .s_axi_wuser({ s14_axi_wuser, s13_axi_wuser, s12_axi_wuser, s11_axi_wuser, s10_axi_wuser, s09_axi_wuser, s08_axi_wuser, s07_axi_wuser, s06_axi_wuser, s05_axi_wuser, s04_axi_wuser, s03_axi_wuser, s02_axi_wuser, s01_axi_wuser, s00_axi_wuser }), - .s_axi_wvalid({ s14_axi_wvalid, s13_axi_wvalid, s12_axi_wvalid, s11_axi_wvalid, s10_axi_wvalid, s09_axi_wvalid, s08_axi_wvalid, s07_axi_wvalid, s06_axi_wvalid, s05_axi_wvalid, s04_axi_wvalid, s03_axi_wvalid, s02_axi_wvalid, s01_axi_wvalid, s00_axi_wvalid }), - .s_axi_wready({ s14_axi_wready, s13_axi_wready, s12_axi_wready, s11_axi_wready, s10_axi_wready, s09_axi_wready, s08_axi_wready, s07_axi_wready, s06_axi_wready, s05_axi_wready, s04_axi_wready, s03_axi_wready, s02_axi_wready, s01_axi_wready, s00_axi_wready }), - .s_axi_bid({ s14_axi_bid, s13_axi_bid, s12_axi_bid, s11_axi_bid, s10_axi_bid, s09_axi_bid, s08_axi_bid, s07_axi_bid, s06_axi_bid, s05_axi_bid, s04_axi_bid, s03_axi_bid, s02_axi_bid, s01_axi_bid, s00_axi_bid }), - .s_axi_bresp({ s14_axi_bresp, s13_axi_bresp, s12_axi_bresp, s11_axi_bresp, s10_axi_bresp, s09_axi_bresp, s08_axi_bresp, s07_axi_bresp, s06_axi_bresp, s05_axi_bresp, s04_axi_bresp, s03_axi_bresp, s02_axi_bresp, s01_axi_bresp, s00_axi_bresp }), - .s_axi_buser({ s14_axi_buser, s13_axi_buser, s12_axi_buser, s11_axi_buser, s10_axi_buser, s09_axi_buser, s08_axi_buser, s07_axi_buser, s06_axi_buser, s05_axi_buser, s04_axi_buser, s03_axi_buser, s02_axi_buser, s01_axi_buser, s00_axi_buser }), - .s_axi_bvalid({ s14_axi_bvalid, s13_axi_bvalid, s12_axi_bvalid, s11_axi_bvalid, s10_axi_bvalid, s09_axi_bvalid, s08_axi_bvalid, s07_axi_bvalid, s06_axi_bvalid, s05_axi_bvalid, s04_axi_bvalid, s03_axi_bvalid, s02_axi_bvalid, s01_axi_bvalid, s00_axi_bvalid }), - .s_axi_bready({ s14_axi_bready, s13_axi_bready, s12_axi_bready, s11_axi_bready, s10_axi_bready, s09_axi_bready, s08_axi_bready, s07_axi_bready, s06_axi_bready, s05_axi_bready, s04_axi_bready, s03_axi_bready, s02_axi_bready, s01_axi_bready, s00_axi_bready }), - .s_axi_arid({ s14_axi_arid, s13_axi_arid, s12_axi_arid, s11_axi_arid, s10_axi_arid, s09_axi_arid, s08_axi_arid, s07_axi_arid, s06_axi_arid, s05_axi_arid, s04_axi_arid, s03_axi_arid, s02_axi_arid, s01_axi_arid, s00_axi_arid }), - .s_axi_araddr({ s14_axi_araddr, s13_axi_araddr, s12_axi_araddr, s11_axi_araddr, s10_axi_araddr, s09_axi_araddr, s08_axi_araddr, s07_axi_araddr, s06_axi_araddr, s05_axi_araddr, s04_axi_araddr, s03_axi_araddr, s02_axi_araddr, s01_axi_araddr, s00_axi_araddr }), - .s_axi_arlen({ s14_axi_arlen, s13_axi_arlen, s12_axi_arlen, s11_axi_arlen, s10_axi_arlen, s09_axi_arlen, s08_axi_arlen, s07_axi_arlen, s06_axi_arlen, s05_axi_arlen, s04_axi_arlen, s03_axi_arlen, s02_axi_arlen, s01_axi_arlen, s00_axi_arlen }), - .s_axi_arsize({ s14_axi_arsize, s13_axi_arsize, s12_axi_arsize, s11_axi_arsize, s10_axi_arsize, s09_axi_arsize, s08_axi_arsize, s07_axi_arsize, s06_axi_arsize, s05_axi_arsize, s04_axi_arsize, s03_axi_arsize, s02_axi_arsize, s01_axi_arsize, s00_axi_arsize }), - .s_axi_arburst({ s14_axi_arburst, s13_axi_arburst, s12_axi_arburst, s11_axi_arburst, s10_axi_arburst, s09_axi_arburst, s08_axi_arburst, s07_axi_arburst, s06_axi_arburst, s05_axi_arburst, s04_axi_arburst, s03_axi_arburst, s02_axi_arburst, s01_axi_arburst, s00_axi_arburst }), - .s_axi_arlock({ s14_axi_arlock, s13_axi_arlock, s12_axi_arlock, s11_axi_arlock, s10_axi_arlock, s09_axi_arlock, s08_axi_arlock, s07_axi_arlock, s06_axi_arlock, s05_axi_arlock, s04_axi_arlock, s03_axi_arlock, s02_axi_arlock, s01_axi_arlock, s00_axi_arlock }), - .s_axi_arcache({ s14_axi_arcache, s13_axi_arcache, s12_axi_arcache, s11_axi_arcache, s10_axi_arcache, s09_axi_arcache, s08_axi_arcache, s07_axi_arcache, s06_axi_arcache, s05_axi_arcache, s04_axi_arcache, s03_axi_arcache, s02_axi_arcache, s01_axi_arcache, s00_axi_arcache }), - .s_axi_arprot({ s14_axi_arprot, s13_axi_arprot, s12_axi_arprot, s11_axi_arprot, s10_axi_arprot, s09_axi_arprot, s08_axi_arprot, s07_axi_arprot, s06_axi_arprot, s05_axi_arprot, s04_axi_arprot, s03_axi_arprot, s02_axi_arprot, s01_axi_arprot, s00_axi_arprot }), - .s_axi_arqos({ s14_axi_arqos, s13_axi_arqos, s12_axi_arqos, s11_axi_arqos, s10_axi_arqos, s09_axi_arqos, s08_axi_arqos, s07_axi_arqos, s06_axi_arqos, s05_axi_arqos, s04_axi_arqos, s03_axi_arqos, s02_axi_arqos, s01_axi_arqos, s00_axi_arqos }), - .s_axi_aruser({ s14_axi_aruser, s13_axi_aruser, s12_axi_aruser, s11_axi_aruser, s10_axi_aruser, s09_axi_aruser, s08_axi_aruser, s07_axi_aruser, s06_axi_aruser, s05_axi_aruser, s04_axi_aruser, s03_axi_aruser, s02_axi_aruser, s01_axi_aruser, s00_axi_aruser }), - .s_axi_arvalid({ s14_axi_arvalid, s13_axi_arvalid, s12_axi_arvalid, s11_axi_arvalid, s10_axi_arvalid, s09_axi_arvalid, s08_axi_arvalid, s07_axi_arvalid, s06_axi_arvalid, s05_axi_arvalid, s04_axi_arvalid, s03_axi_arvalid, s02_axi_arvalid, s01_axi_arvalid, s00_axi_arvalid }), - .s_axi_arready({ s14_axi_arready, s13_axi_arready, s12_axi_arready, s11_axi_arready, s10_axi_arready, s09_axi_arready, s08_axi_arready, s07_axi_arready, s06_axi_arready, s05_axi_arready, s04_axi_arready, s03_axi_arready, s02_axi_arready, s01_axi_arready, s00_axi_arready }), - .s_axi_rid({ s14_axi_rid, s13_axi_rid, s12_axi_rid, s11_axi_rid, s10_axi_rid, s09_axi_rid, s08_axi_rid, s07_axi_rid, s06_axi_rid, s05_axi_rid, s04_axi_rid, s03_axi_rid, s02_axi_rid, s01_axi_rid, s00_axi_rid }), - .s_axi_rdata({ s14_axi_rdata, s13_axi_rdata, s12_axi_rdata, s11_axi_rdata, s10_axi_rdata, s09_axi_rdata, s08_axi_rdata, s07_axi_rdata, s06_axi_rdata, s05_axi_rdata, s04_axi_rdata, s03_axi_rdata, s02_axi_rdata, s01_axi_rdata, s00_axi_rdata }), - .s_axi_rresp({ s14_axi_rresp, s13_axi_rresp, s12_axi_rresp, s11_axi_rresp, s10_axi_rresp, s09_axi_rresp, s08_axi_rresp, s07_axi_rresp, s06_axi_rresp, s05_axi_rresp, s04_axi_rresp, s03_axi_rresp, s02_axi_rresp, s01_axi_rresp, s00_axi_rresp }), - .s_axi_rlast({ s14_axi_rlast, s13_axi_rlast, s12_axi_rlast, s11_axi_rlast, s10_axi_rlast, s09_axi_rlast, s08_axi_rlast, s07_axi_rlast, s06_axi_rlast, s05_axi_rlast, s04_axi_rlast, s03_axi_rlast, s02_axi_rlast, s01_axi_rlast, s00_axi_rlast }), - .s_axi_ruser({ s14_axi_ruser, s13_axi_ruser, s12_axi_ruser, s11_axi_ruser, s10_axi_ruser, s09_axi_ruser, s08_axi_ruser, s07_axi_ruser, s06_axi_ruser, s05_axi_ruser, s04_axi_ruser, s03_axi_ruser, s02_axi_ruser, s01_axi_ruser, s00_axi_ruser }), - .s_axi_rvalid({ s14_axi_rvalid, s13_axi_rvalid, s12_axi_rvalid, s11_axi_rvalid, s10_axi_rvalid, s09_axi_rvalid, s08_axi_rvalid, s07_axi_rvalid, s06_axi_rvalid, s05_axi_rvalid, s04_axi_rvalid, s03_axi_rvalid, s02_axi_rvalid, s01_axi_rvalid, s00_axi_rvalid }), - .s_axi_rready({ s14_axi_rready, s13_axi_rready, s12_axi_rready, s11_axi_rready, s10_axi_rready, s09_axi_rready, s08_axi_rready, s07_axi_rready, s06_axi_rready, s05_axi_rready, s04_axi_rready, s03_axi_rready, s02_axi_rready, s01_axi_rready, s00_axi_rready }), - .m_axi_awid({ m00_axi_awid }), - .m_axi_awaddr({ m00_axi_awaddr }), - .m_axi_awlen({ m00_axi_awlen }), - .m_axi_awsize({ m00_axi_awsize }), - .m_axi_awburst({ m00_axi_awburst }), - .m_axi_awlock({ m00_axi_awlock }), - .m_axi_awcache({ m00_axi_awcache }), - .m_axi_awprot({ m00_axi_awprot }), - .m_axi_awqos({ m00_axi_awqos }), - .m_axi_awregion({ m00_axi_awregion }), - .m_axi_awuser({ m00_axi_awuser }), - .m_axi_awvalid({ m00_axi_awvalid }), - .m_axi_awready({ m00_axi_awready }), - .m_axi_wdata({ m00_axi_wdata }), - .m_axi_wstrb({ m00_axi_wstrb }), - .m_axi_wlast({ m00_axi_wlast }), - .m_axi_wuser({ m00_axi_wuser }), - .m_axi_wvalid({ m00_axi_wvalid }), - .m_axi_wready({ m00_axi_wready }), - .m_axi_bid({ m00_axi_bid }), - .m_axi_bresp({ m00_axi_bresp }), - .m_axi_buser({ m00_axi_buser }), - .m_axi_bvalid({ m00_axi_bvalid }), - .m_axi_bready({ m00_axi_bready }), - .m_axi_arid({ m00_axi_arid }), - .m_axi_araddr({ m00_axi_araddr }), - .m_axi_arlen({ m00_axi_arlen }), - .m_axi_arsize({ m00_axi_arsize }), - .m_axi_arburst({ m00_axi_arburst }), - .m_axi_arlock({ m00_axi_arlock }), - .m_axi_arcache({ m00_axi_arcache }), - .m_axi_arprot({ m00_axi_arprot }), - .m_axi_arqos({ m00_axi_arqos }), - .m_axi_arregion({ m00_axi_arregion }), - .m_axi_aruser({ m00_axi_aruser }), - .m_axi_arvalid({ m00_axi_arvalid }), - .m_axi_arready({ m00_axi_arready }), - .m_axi_rid({ m00_axi_rid }), - .m_axi_rdata({ m00_axi_rdata }), - .m_axi_rresp({ m00_axi_rresp }), - .m_axi_rlast({ m00_axi_rlast }), - .m_axi_ruser({ m00_axi_ruser }), - .m_axi_rvalid({ m00_axi_rvalid }), - .m_axi_rready({ m00_axi_rready }) -); - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_register_rd.v b/xls/modules/zstd/external/axi_register_rd.v deleted file mode 100644 index c0df03a03f..0000000000 --- a/xls/modules/zstd/external/axi_register_rd.v +++ /dev/null @@ -1,530 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 register (read) - */ -module axi_register_rd # -( - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Width of ID signal - parameter ID_WIDTH = 8, - // Propagate aruser signal - parameter ARUSER_ENABLE = 0, - // Width of aruser signal - parameter ARUSER_WIDTH = 1, - // Propagate ruser signal - parameter RUSER_ENABLE = 0, - // Width of ruser signal - parameter RUSER_WIDTH = 1, - // AR channel register type - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter AR_REG_TYPE = 1, - // R channel register type - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter R_REG_TYPE = 2 -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interface - */ - input wire [ID_WIDTH-1:0] s_axi_arid, - input wire [ADDR_WIDTH-1:0] s_axi_araddr, - input wire [7:0] s_axi_arlen, - input wire [2:0] s_axi_arsize, - input wire [1:0] s_axi_arburst, - input wire s_axi_arlock, - input wire [3:0] s_axi_arcache, - input wire [2:0] s_axi_arprot, - input wire [3:0] s_axi_arqos, - input wire [3:0] s_axi_arregion, - input wire [ARUSER_WIDTH-1:0] s_axi_aruser, - input wire s_axi_arvalid, - output wire s_axi_arready, - output wire [ID_WIDTH-1:0] s_axi_rid, - output wire [DATA_WIDTH-1:0] s_axi_rdata, - output wire [1:0] s_axi_rresp, - output wire s_axi_rlast, - output wire [RUSER_WIDTH-1:0] s_axi_ruser, - output wire s_axi_rvalid, - input wire s_axi_rready, - - /* - * AXI master interface - */ - output wire [ID_WIDTH-1:0] m_axi_arid, - output wire [ADDR_WIDTH-1:0] m_axi_araddr, - output wire [7:0] m_axi_arlen, - output wire [2:0] m_axi_arsize, - output wire [1:0] m_axi_arburst, - output wire m_axi_arlock, - output wire [3:0] m_axi_arcache, - output wire [2:0] m_axi_arprot, - output wire [3:0] m_axi_arqos, - output wire [3:0] m_axi_arregion, - output wire [ARUSER_WIDTH-1:0] m_axi_aruser, - output wire m_axi_arvalid, - input wire m_axi_arready, - input wire [ID_WIDTH-1:0] m_axi_rid, - input wire [DATA_WIDTH-1:0] m_axi_rdata, - input wire [1:0] m_axi_rresp, - input wire m_axi_rlast, - input wire [RUSER_WIDTH-1:0] m_axi_ruser, - input wire m_axi_rvalid, - output wire m_axi_rready -); - -generate - -// AR channel - -if (AR_REG_TYPE > 1) begin -// skid buffer, no bubble cycles - -// datapath registers -reg s_axi_arready_reg = 1'b0; - -reg [ID_WIDTH-1:0] m_axi_arid_reg = {ID_WIDTH{1'b0}}; -reg [ADDR_WIDTH-1:0] m_axi_araddr_reg = {ADDR_WIDTH{1'b0}}; -reg [7:0] m_axi_arlen_reg = 8'd0; -reg [2:0] m_axi_arsize_reg = 3'd0; -reg [1:0] m_axi_arburst_reg = 2'd0; -reg m_axi_arlock_reg = 1'b0; -reg [3:0] m_axi_arcache_reg = 4'd0; -reg [2:0] m_axi_arprot_reg = 3'd0; -reg [3:0] m_axi_arqos_reg = 4'd0; -reg [3:0] m_axi_arregion_reg = 4'd0; -reg [ARUSER_WIDTH-1:0] m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}}; -reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next; - -reg [ID_WIDTH-1:0] temp_m_axi_arid_reg = {ID_WIDTH{1'b0}}; -reg [ADDR_WIDTH-1:0] temp_m_axi_araddr_reg = {ADDR_WIDTH{1'b0}}; -reg [7:0] temp_m_axi_arlen_reg = 8'd0; -reg [2:0] temp_m_axi_arsize_reg = 3'd0; -reg [1:0] temp_m_axi_arburst_reg = 2'd0; -reg temp_m_axi_arlock_reg = 1'b0; -reg [3:0] temp_m_axi_arcache_reg = 4'd0; -reg [2:0] temp_m_axi_arprot_reg = 3'd0; -reg [3:0] temp_m_axi_arqos_reg = 4'd0; -reg [3:0] temp_m_axi_arregion_reg = 4'd0; -reg [ARUSER_WIDTH-1:0] temp_m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}}; -reg temp_m_axi_arvalid_reg = 1'b0, temp_m_axi_arvalid_next; - -// datapath control -reg store_axi_ar_input_to_output; -reg store_axi_ar_input_to_temp; -reg store_axi_ar_temp_to_output; - -assign s_axi_arready = s_axi_arready_reg; - -assign m_axi_arid = m_axi_arid_reg; -assign m_axi_araddr = m_axi_araddr_reg; -assign m_axi_arlen = m_axi_arlen_reg; -assign m_axi_arsize = m_axi_arsize_reg; -assign m_axi_arburst = m_axi_arburst_reg; -assign m_axi_arlock = m_axi_arlock_reg; -assign m_axi_arcache = m_axi_arcache_reg; -assign m_axi_arprot = m_axi_arprot_reg; -assign m_axi_arqos = m_axi_arqos_reg; -assign m_axi_arregion = m_axi_arregion_reg; -assign m_axi_aruser = ARUSER_ENABLE ? m_axi_aruser_reg : {ARUSER_WIDTH{1'b0}}; -assign m_axi_arvalid = m_axi_arvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -wire s_axi_arready_early = m_axi_arready | (~temp_m_axi_arvalid_reg & (~m_axi_arvalid_reg | ~s_axi_arvalid)); - -always @* begin - // transfer sink ready state to source - m_axi_arvalid_next = m_axi_arvalid_reg; - temp_m_axi_arvalid_next = temp_m_axi_arvalid_reg; - - store_axi_ar_input_to_output = 1'b0; - store_axi_ar_input_to_temp = 1'b0; - store_axi_ar_temp_to_output = 1'b0; - - if (s_axi_arready_reg) begin - // input is ready - if (m_axi_arready | ~m_axi_arvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axi_arvalid_next = s_axi_arvalid; - store_axi_ar_input_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axi_arvalid_next = s_axi_arvalid; - store_axi_ar_input_to_temp = 1'b1; - end - end else if (m_axi_arready) begin - // input is not ready, but output is ready - m_axi_arvalid_next = temp_m_axi_arvalid_reg; - temp_m_axi_arvalid_next = 1'b0; - store_axi_ar_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_arready_reg <= 1'b0; - m_axi_arvalid_reg <= 1'b0; - temp_m_axi_arvalid_reg <= 1'b0; - end else begin - s_axi_arready_reg <= s_axi_arready_early; - m_axi_arvalid_reg <= m_axi_arvalid_next; - temp_m_axi_arvalid_reg <= temp_m_axi_arvalid_next; - end - - // datapath - if (store_axi_ar_input_to_output) begin - m_axi_arid_reg <= s_axi_arid; - m_axi_araddr_reg <= s_axi_araddr; - m_axi_arlen_reg <= s_axi_arlen; - m_axi_arsize_reg <= s_axi_arsize; - m_axi_arburst_reg <= s_axi_arburst; - m_axi_arlock_reg <= s_axi_arlock; - m_axi_arcache_reg <= s_axi_arcache; - m_axi_arprot_reg <= s_axi_arprot; - m_axi_arqos_reg <= s_axi_arqos; - m_axi_arregion_reg <= s_axi_arregion; - m_axi_aruser_reg <= s_axi_aruser; - end else if (store_axi_ar_temp_to_output) begin - m_axi_arid_reg <= temp_m_axi_arid_reg; - m_axi_araddr_reg <= temp_m_axi_araddr_reg; - m_axi_arlen_reg <= temp_m_axi_arlen_reg; - m_axi_arsize_reg <= temp_m_axi_arsize_reg; - m_axi_arburst_reg <= temp_m_axi_arburst_reg; - m_axi_arlock_reg <= temp_m_axi_arlock_reg; - m_axi_arcache_reg <= temp_m_axi_arcache_reg; - m_axi_arprot_reg <= temp_m_axi_arprot_reg; - m_axi_arqos_reg <= temp_m_axi_arqos_reg; - m_axi_arregion_reg <= temp_m_axi_arregion_reg; - m_axi_aruser_reg <= temp_m_axi_aruser_reg; - end - - if (store_axi_ar_input_to_temp) begin - temp_m_axi_arid_reg <= s_axi_arid; - temp_m_axi_araddr_reg <= s_axi_araddr; - temp_m_axi_arlen_reg <= s_axi_arlen; - temp_m_axi_arsize_reg <= s_axi_arsize; - temp_m_axi_arburst_reg <= s_axi_arburst; - temp_m_axi_arlock_reg <= s_axi_arlock; - temp_m_axi_arcache_reg <= s_axi_arcache; - temp_m_axi_arprot_reg <= s_axi_arprot; - temp_m_axi_arqos_reg <= s_axi_arqos; - temp_m_axi_arregion_reg <= s_axi_arregion; - temp_m_axi_aruser_reg <= s_axi_aruser; - end -end - -end else if (AR_REG_TYPE == 1) begin -// simple register, inserts bubble cycles - -// datapath registers -reg s_axi_arready_reg = 1'b0; - -reg [ID_WIDTH-1:0] m_axi_arid_reg = {ID_WIDTH{1'b0}}; -reg [ADDR_WIDTH-1:0] m_axi_araddr_reg = {ADDR_WIDTH{1'b0}}; -reg [7:0] m_axi_arlen_reg = 8'd0; -reg [2:0] m_axi_arsize_reg = 3'd0; -reg [1:0] m_axi_arburst_reg = 2'd0; -reg m_axi_arlock_reg = 1'b0; -reg [3:0] m_axi_arcache_reg = 4'd0; -reg [2:0] m_axi_arprot_reg = 3'd0; -reg [3:0] m_axi_arqos_reg = 4'd0; -reg [3:0] m_axi_arregion_reg = 4'd0; -reg [ARUSER_WIDTH-1:0] m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}}; -reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next; - -// datapath control -reg store_axi_ar_input_to_output; - -assign s_axi_arready = s_axi_arready_reg; - -assign m_axi_arid = m_axi_arid_reg; -assign m_axi_araddr = m_axi_araddr_reg; -assign m_axi_arlen = m_axi_arlen_reg; -assign m_axi_arsize = m_axi_arsize_reg; -assign m_axi_arburst = m_axi_arburst_reg; -assign m_axi_arlock = m_axi_arlock_reg; -assign m_axi_arcache = m_axi_arcache_reg; -assign m_axi_arprot = m_axi_arprot_reg; -assign m_axi_arqos = m_axi_arqos_reg; -assign m_axi_arregion = m_axi_arregion_reg; -assign m_axi_aruser = ARUSER_ENABLE ? m_axi_aruser_reg : {ARUSER_WIDTH{1'b0}}; -assign m_axi_arvalid = m_axi_arvalid_reg; - -// enable ready input next cycle if output buffer will be empty -wire s_axi_arready_early = !m_axi_arvalid_next; - -always @* begin - // transfer sink ready state to source - m_axi_arvalid_next = m_axi_arvalid_reg; - - store_axi_ar_input_to_output = 1'b0; - - if (s_axi_arready_reg) begin - m_axi_arvalid_next = s_axi_arvalid; - store_axi_ar_input_to_output = 1'b1; - end else if (m_axi_arready) begin - m_axi_arvalid_next = 1'b0; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_arready_reg <= 1'b0; - m_axi_arvalid_reg <= 1'b0; - end else begin - s_axi_arready_reg <= s_axi_arready_early; - m_axi_arvalid_reg <= m_axi_arvalid_next; - end - - // datapath - if (store_axi_ar_input_to_output) begin - m_axi_arid_reg <= s_axi_arid; - m_axi_araddr_reg <= s_axi_araddr; - m_axi_arlen_reg <= s_axi_arlen; - m_axi_arsize_reg <= s_axi_arsize; - m_axi_arburst_reg <= s_axi_arburst; - m_axi_arlock_reg <= s_axi_arlock; - m_axi_arcache_reg <= s_axi_arcache; - m_axi_arprot_reg <= s_axi_arprot; - m_axi_arqos_reg <= s_axi_arqos; - m_axi_arregion_reg <= s_axi_arregion; - m_axi_aruser_reg <= s_axi_aruser; - end -end - -end else begin - - // bypass AR channel - assign m_axi_arid = s_axi_arid; - assign m_axi_araddr = s_axi_araddr; - assign m_axi_arlen = s_axi_arlen; - assign m_axi_arsize = s_axi_arsize; - assign m_axi_arburst = s_axi_arburst; - assign m_axi_arlock = s_axi_arlock; - assign m_axi_arcache = s_axi_arcache; - assign m_axi_arprot = s_axi_arprot; - assign m_axi_arqos = s_axi_arqos; - assign m_axi_arregion = s_axi_arregion; - assign m_axi_aruser = ARUSER_ENABLE ? s_axi_aruser : {ARUSER_WIDTH{1'b0}}; - assign m_axi_arvalid = s_axi_arvalid; - assign s_axi_arready = m_axi_arready; - -end - -// R channel - -if (R_REG_TYPE > 1) begin -// skid buffer, no bubble cycles - -// datapath registers -reg m_axi_rready_reg = 1'b0; - -reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; -reg [1:0] s_axi_rresp_reg = 2'b0; -reg s_axi_rlast_reg = 1'b0; -reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = {RUSER_WIDTH{1'b0}}; -reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next; - -reg [ID_WIDTH-1:0] temp_s_axi_rid_reg = {ID_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] temp_s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; -reg [1:0] temp_s_axi_rresp_reg = 2'b0; -reg temp_s_axi_rlast_reg = 1'b0; -reg [RUSER_WIDTH-1:0] temp_s_axi_ruser_reg = {RUSER_WIDTH{1'b0}}; -reg temp_s_axi_rvalid_reg = 1'b0, temp_s_axi_rvalid_next; - -// datapath control -reg store_axi_r_input_to_output; -reg store_axi_r_input_to_temp; -reg store_axi_r_temp_to_output; - -assign m_axi_rready = m_axi_rready_reg; - -assign s_axi_rid = s_axi_rid_reg; -assign s_axi_rdata = s_axi_rdata_reg; -assign s_axi_rresp = s_axi_rresp_reg; -assign s_axi_rlast = s_axi_rlast_reg; -assign s_axi_ruser = RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}}; -assign s_axi_rvalid = s_axi_rvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -wire m_axi_rready_early = s_axi_rready | (~temp_s_axi_rvalid_reg & (~s_axi_rvalid_reg | ~m_axi_rvalid)); - -always @* begin - // transfer sink ready state to source - s_axi_rvalid_next = s_axi_rvalid_reg; - temp_s_axi_rvalid_next = temp_s_axi_rvalid_reg; - - store_axi_r_input_to_output = 1'b0; - store_axi_r_input_to_temp = 1'b0; - store_axi_r_temp_to_output = 1'b0; - - if (m_axi_rready_reg) begin - // input is ready - if (s_axi_rready | ~s_axi_rvalid_reg) begin - // output is ready or currently not valid, transfer data to output - s_axi_rvalid_next = m_axi_rvalid; - store_axi_r_input_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_s_axi_rvalid_next = m_axi_rvalid; - store_axi_r_input_to_temp = 1'b1; - end - end else if (s_axi_rready) begin - // input is not ready, but output is ready - s_axi_rvalid_next = temp_s_axi_rvalid_reg; - temp_s_axi_rvalid_next = 1'b0; - store_axi_r_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - m_axi_rready_reg <= 1'b0; - s_axi_rvalid_reg <= 1'b0; - temp_s_axi_rvalid_reg <= 1'b0; - end else begin - m_axi_rready_reg <= m_axi_rready_early; - s_axi_rvalid_reg <= s_axi_rvalid_next; - temp_s_axi_rvalid_reg <= temp_s_axi_rvalid_next; - end - - // datapath - if (store_axi_r_input_to_output) begin - s_axi_rid_reg <= m_axi_rid; - s_axi_rdata_reg <= m_axi_rdata; - s_axi_rresp_reg <= m_axi_rresp; - s_axi_rlast_reg <= m_axi_rlast; - s_axi_ruser_reg <= m_axi_ruser; - end else if (store_axi_r_temp_to_output) begin - s_axi_rid_reg <= temp_s_axi_rid_reg; - s_axi_rdata_reg <= temp_s_axi_rdata_reg; - s_axi_rresp_reg <= temp_s_axi_rresp_reg; - s_axi_rlast_reg <= temp_s_axi_rlast_reg; - s_axi_ruser_reg <= temp_s_axi_ruser_reg; - end - - if (store_axi_r_input_to_temp) begin - temp_s_axi_rid_reg <= m_axi_rid; - temp_s_axi_rdata_reg <= m_axi_rdata; - temp_s_axi_rresp_reg <= m_axi_rresp; - temp_s_axi_rlast_reg <= m_axi_rlast; - temp_s_axi_ruser_reg <= m_axi_ruser; - end -end - -end else if (R_REG_TYPE == 1) begin -// simple register, inserts bubble cycles - -// datapath registers -reg m_axi_rready_reg = 1'b0; - -reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}; -reg [1:0] s_axi_rresp_reg = 2'b0; -reg s_axi_rlast_reg = 1'b0; -reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = {RUSER_WIDTH{1'b0}}; -reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next; - -// datapath control -reg store_axi_r_input_to_output; - -assign m_axi_rready = m_axi_rready_reg; - -assign s_axi_rid = s_axi_rid_reg; -assign s_axi_rdata = s_axi_rdata_reg; -assign s_axi_rresp = s_axi_rresp_reg; -assign s_axi_rlast = s_axi_rlast_reg; -assign s_axi_ruser = RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}}; -assign s_axi_rvalid = s_axi_rvalid_reg; - -// enable ready input next cycle if output buffer will be empty -wire m_axi_rready_early = !s_axi_rvalid_next; - -always @* begin - // transfer sink ready state to source - s_axi_rvalid_next = s_axi_rvalid_reg; - - store_axi_r_input_to_output = 1'b0; - - if (m_axi_rready_reg) begin - s_axi_rvalid_next = m_axi_rvalid; - store_axi_r_input_to_output = 1'b1; - end else if (s_axi_rready) begin - s_axi_rvalid_next = 1'b0; - end -end - -always @(posedge clk) begin - if (rst) begin - m_axi_rready_reg <= 1'b0; - s_axi_rvalid_reg <= 1'b0; - end else begin - m_axi_rready_reg <= m_axi_rready_early; - s_axi_rvalid_reg <= s_axi_rvalid_next; - end - - // datapath - if (store_axi_r_input_to_output) begin - s_axi_rid_reg <= m_axi_rid; - s_axi_rdata_reg <= m_axi_rdata; - s_axi_rresp_reg <= m_axi_rresp; - s_axi_rlast_reg <= m_axi_rlast; - s_axi_ruser_reg <= m_axi_ruser; - end -end - -end else begin - - // bypass R channel - assign s_axi_rid = m_axi_rid; - assign s_axi_rdata = m_axi_rdata; - assign s_axi_rresp = m_axi_rresp; - assign s_axi_rlast = m_axi_rlast; - assign s_axi_ruser = RUSER_ENABLE ? m_axi_ruser : {RUSER_WIDTH{1'b0}}; - assign s_axi_rvalid = m_axi_rvalid; - assign m_axi_rready = s_axi_rready; - -end - -endgenerate - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/axi_register_wr.v b/xls/modules/zstd/external/axi_register_wr.v deleted file mode 100644 index 9176d6ba95..0000000000 --- a/xls/modules/zstd/external/axi_register_wr.v +++ /dev/null @@ -1,691 +0,0 @@ -/* - -Copyright (c) 2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * AXI4 register (write) - */ -module axi_register_wr # -( - // Width of data bus in bits - parameter DATA_WIDTH = 32, - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH/8), - // Width of ID signal - parameter ID_WIDTH = 8, - // Propagate awuser signal - parameter AWUSER_ENABLE = 0, - // Width of awuser signal - parameter AWUSER_WIDTH = 1, - // Propagate wuser signal - parameter WUSER_ENABLE = 0, - // Width of wuser signal - parameter WUSER_WIDTH = 1, - // Propagate buser signal - parameter BUSER_ENABLE = 0, - // Width of buser signal - parameter BUSER_WIDTH = 1, - // AW channel register type - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter AW_REG_TYPE = 1, - // W channel register type - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter W_REG_TYPE = 2, - // B channel register type - // 0 to bypass, 1 for simple buffer, 2 for skid buffer - parameter B_REG_TYPE = 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI slave interface - */ - input wire [ID_WIDTH-1:0] s_axi_awid, - input wire [ADDR_WIDTH-1:0] s_axi_awaddr, - input wire [7:0] s_axi_awlen, - input wire [2:0] s_axi_awsize, - input wire [1:0] s_axi_awburst, - input wire s_axi_awlock, - input wire [3:0] s_axi_awcache, - input wire [2:0] s_axi_awprot, - input wire [3:0] s_axi_awqos, - input wire [3:0] s_axi_awregion, - input wire [AWUSER_WIDTH-1:0] s_axi_awuser, - input wire s_axi_awvalid, - output wire s_axi_awready, - input wire [DATA_WIDTH-1:0] s_axi_wdata, - input wire [STRB_WIDTH-1:0] s_axi_wstrb, - input wire s_axi_wlast, - input wire [WUSER_WIDTH-1:0] s_axi_wuser, - input wire s_axi_wvalid, - output wire s_axi_wready, - output wire [ID_WIDTH-1:0] s_axi_bid, - output wire [1:0] s_axi_bresp, - output wire [BUSER_WIDTH-1:0] s_axi_buser, - output wire s_axi_bvalid, - input wire s_axi_bready, - - /* - * AXI master interface - */ - output wire [ID_WIDTH-1:0] m_axi_awid, - output wire [ADDR_WIDTH-1:0] m_axi_awaddr, - output wire [7:0] m_axi_awlen, - output wire [2:0] m_axi_awsize, - output wire [1:0] m_axi_awburst, - output wire m_axi_awlock, - output wire [3:0] m_axi_awcache, - output wire [2:0] m_axi_awprot, - output wire [3:0] m_axi_awqos, - output wire [3:0] m_axi_awregion, - output wire [AWUSER_WIDTH-1:0] m_axi_awuser, - output wire m_axi_awvalid, - input wire m_axi_awready, - output wire [DATA_WIDTH-1:0] m_axi_wdata, - output wire [STRB_WIDTH-1:0] m_axi_wstrb, - output wire m_axi_wlast, - output wire [WUSER_WIDTH-1:0] m_axi_wuser, - output wire m_axi_wvalid, - input wire m_axi_wready, - input wire [ID_WIDTH-1:0] m_axi_bid, - input wire [1:0] m_axi_bresp, - input wire [BUSER_WIDTH-1:0] m_axi_buser, - input wire m_axi_bvalid, - output wire m_axi_bready -); - -generate - -// AW channel - -if (AW_REG_TYPE > 1) begin -// skid buffer, no bubble cycles - -// datapath registers -reg s_axi_awready_reg = 1'b0; - -reg [ID_WIDTH-1:0] m_axi_awid_reg = {ID_WIDTH{1'b0}}; -reg [ADDR_WIDTH-1:0] m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}}; -reg [7:0] m_axi_awlen_reg = 8'd0; -reg [2:0] m_axi_awsize_reg = 3'd0; -reg [1:0] m_axi_awburst_reg = 2'd0; -reg m_axi_awlock_reg = 1'b0; -reg [3:0] m_axi_awcache_reg = 4'd0; -reg [2:0] m_axi_awprot_reg = 3'd0; -reg [3:0] m_axi_awqos_reg = 4'd0; -reg [3:0] m_axi_awregion_reg = 4'd0; -reg [AWUSER_WIDTH-1:0] m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}}; -reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next; - -reg [ID_WIDTH-1:0] temp_m_axi_awid_reg = {ID_WIDTH{1'b0}}; -reg [ADDR_WIDTH-1:0] temp_m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}}; -reg [7:0] temp_m_axi_awlen_reg = 8'd0; -reg [2:0] temp_m_axi_awsize_reg = 3'd0; -reg [1:0] temp_m_axi_awburst_reg = 2'd0; -reg temp_m_axi_awlock_reg = 1'b0; -reg [3:0] temp_m_axi_awcache_reg = 4'd0; -reg [2:0] temp_m_axi_awprot_reg = 3'd0; -reg [3:0] temp_m_axi_awqos_reg = 4'd0; -reg [3:0] temp_m_axi_awregion_reg = 4'd0; -reg [AWUSER_WIDTH-1:0] temp_m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}}; -reg temp_m_axi_awvalid_reg = 1'b0, temp_m_axi_awvalid_next; - -// datapath control -reg store_axi_aw_input_to_output; -reg store_axi_aw_input_to_temp; -reg store_axi_aw_temp_to_output; - -assign s_axi_awready = s_axi_awready_reg; - -assign m_axi_awid = m_axi_awid_reg; -assign m_axi_awaddr = m_axi_awaddr_reg; -assign m_axi_awlen = m_axi_awlen_reg; -assign m_axi_awsize = m_axi_awsize_reg; -assign m_axi_awburst = m_axi_awburst_reg; -assign m_axi_awlock = m_axi_awlock_reg; -assign m_axi_awcache = m_axi_awcache_reg; -assign m_axi_awprot = m_axi_awprot_reg; -assign m_axi_awqos = m_axi_awqos_reg; -assign m_axi_awregion = m_axi_awregion_reg; -assign m_axi_awuser = AWUSER_ENABLE ? m_axi_awuser_reg : {AWUSER_WIDTH{1'b0}}; -assign m_axi_awvalid = m_axi_awvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -wire s_axi_awready_early = m_axi_awready | (~temp_m_axi_awvalid_reg & (~m_axi_awvalid_reg | ~s_axi_awvalid)); - -always @* begin - // transfer sink ready state to source - m_axi_awvalid_next = m_axi_awvalid_reg; - temp_m_axi_awvalid_next = temp_m_axi_awvalid_reg; - - store_axi_aw_input_to_output = 1'b0; - store_axi_aw_input_to_temp = 1'b0; - store_axi_aw_temp_to_output = 1'b0; - - if (s_axi_awready_reg) begin - // input is ready - if (m_axi_awready | ~m_axi_awvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axi_awvalid_next = s_axi_awvalid; - store_axi_aw_input_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axi_awvalid_next = s_axi_awvalid; - store_axi_aw_input_to_temp = 1'b1; - end - end else if (m_axi_awready) begin - // input is not ready, but output is ready - m_axi_awvalid_next = temp_m_axi_awvalid_reg; - temp_m_axi_awvalid_next = 1'b0; - store_axi_aw_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_awready_reg <= 1'b0; - m_axi_awvalid_reg <= 1'b0; - temp_m_axi_awvalid_reg <= 1'b0; - end else begin - s_axi_awready_reg <= s_axi_awready_early; - m_axi_awvalid_reg <= m_axi_awvalid_next; - temp_m_axi_awvalid_reg <= temp_m_axi_awvalid_next; - end - - // datapath - if (store_axi_aw_input_to_output) begin - m_axi_awid_reg <= s_axi_awid; - m_axi_awaddr_reg <= s_axi_awaddr; - m_axi_awlen_reg <= s_axi_awlen; - m_axi_awsize_reg <= s_axi_awsize; - m_axi_awburst_reg <= s_axi_awburst; - m_axi_awlock_reg <= s_axi_awlock; - m_axi_awcache_reg <= s_axi_awcache; - m_axi_awprot_reg <= s_axi_awprot; - m_axi_awqos_reg <= s_axi_awqos; - m_axi_awregion_reg <= s_axi_awregion; - m_axi_awuser_reg <= s_axi_awuser; - end else if (store_axi_aw_temp_to_output) begin - m_axi_awid_reg <= temp_m_axi_awid_reg; - m_axi_awaddr_reg <= temp_m_axi_awaddr_reg; - m_axi_awlen_reg <= temp_m_axi_awlen_reg; - m_axi_awsize_reg <= temp_m_axi_awsize_reg; - m_axi_awburst_reg <= temp_m_axi_awburst_reg; - m_axi_awlock_reg <= temp_m_axi_awlock_reg; - m_axi_awcache_reg <= temp_m_axi_awcache_reg; - m_axi_awprot_reg <= temp_m_axi_awprot_reg; - m_axi_awqos_reg <= temp_m_axi_awqos_reg; - m_axi_awregion_reg <= temp_m_axi_awregion_reg; - m_axi_awuser_reg <= temp_m_axi_awuser_reg; - end - - if (store_axi_aw_input_to_temp) begin - temp_m_axi_awid_reg <= s_axi_awid; - temp_m_axi_awaddr_reg <= s_axi_awaddr; - temp_m_axi_awlen_reg <= s_axi_awlen; - temp_m_axi_awsize_reg <= s_axi_awsize; - temp_m_axi_awburst_reg <= s_axi_awburst; - temp_m_axi_awlock_reg <= s_axi_awlock; - temp_m_axi_awcache_reg <= s_axi_awcache; - temp_m_axi_awprot_reg <= s_axi_awprot; - temp_m_axi_awqos_reg <= s_axi_awqos; - temp_m_axi_awregion_reg <= s_axi_awregion; - temp_m_axi_awuser_reg <= s_axi_awuser; - end -end - -end else if (AW_REG_TYPE == 1) begin -// simple register, inserts bubble cycles - -// datapath registers -reg s_axi_awready_reg = 1'b0; - -reg [ID_WIDTH-1:0] m_axi_awid_reg = {ID_WIDTH{1'b0}}; -reg [ADDR_WIDTH-1:0] m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}}; -reg [7:0] m_axi_awlen_reg = 8'd0; -reg [2:0] m_axi_awsize_reg = 3'd0; -reg [1:0] m_axi_awburst_reg = 2'd0; -reg m_axi_awlock_reg = 1'b0; -reg [3:0] m_axi_awcache_reg = 4'd0; -reg [2:0] m_axi_awprot_reg = 3'd0; -reg [3:0] m_axi_awqos_reg = 4'd0; -reg [3:0] m_axi_awregion_reg = 4'd0; -reg [AWUSER_WIDTH-1:0] m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}}; -reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next; - -// datapath control -reg store_axi_aw_input_to_output; - -assign s_axi_awready = s_axi_awready_reg; - -assign m_axi_awid = m_axi_awid_reg; -assign m_axi_awaddr = m_axi_awaddr_reg; -assign m_axi_awlen = m_axi_awlen_reg; -assign m_axi_awsize = m_axi_awsize_reg; -assign m_axi_awburst = m_axi_awburst_reg; -assign m_axi_awlock = m_axi_awlock_reg; -assign m_axi_awcache = m_axi_awcache_reg; -assign m_axi_awprot = m_axi_awprot_reg; -assign m_axi_awqos = m_axi_awqos_reg; -assign m_axi_awregion = m_axi_awregion_reg; -assign m_axi_awuser = AWUSER_ENABLE ? m_axi_awuser_reg : {AWUSER_WIDTH{1'b0}}; -assign m_axi_awvalid = m_axi_awvalid_reg; - -// enable ready input next cycle if output buffer will be empty -wire s_axi_awready_eawly = !m_axi_awvalid_next; - -always @* begin - // transfer sink ready state to source - m_axi_awvalid_next = m_axi_awvalid_reg; - - store_axi_aw_input_to_output = 1'b0; - - if (s_axi_awready_reg) begin - m_axi_awvalid_next = s_axi_awvalid; - store_axi_aw_input_to_output = 1'b1; - end else if (m_axi_awready) begin - m_axi_awvalid_next = 1'b0; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_awready_reg <= 1'b0; - m_axi_awvalid_reg <= 1'b0; - end else begin - s_axi_awready_reg <= s_axi_awready_eawly; - m_axi_awvalid_reg <= m_axi_awvalid_next; - end - - // datapath - if (store_axi_aw_input_to_output) begin - m_axi_awid_reg <= s_axi_awid; - m_axi_awaddr_reg <= s_axi_awaddr; - m_axi_awlen_reg <= s_axi_awlen; - m_axi_awsize_reg <= s_axi_awsize; - m_axi_awburst_reg <= s_axi_awburst; - m_axi_awlock_reg <= s_axi_awlock; - m_axi_awcache_reg <= s_axi_awcache; - m_axi_awprot_reg <= s_axi_awprot; - m_axi_awqos_reg <= s_axi_awqos; - m_axi_awregion_reg <= s_axi_awregion; - m_axi_awuser_reg <= s_axi_awuser; - end -end - -end else begin - - // bypass AW channel - assign m_axi_awid = s_axi_awid; - assign m_axi_awaddr = s_axi_awaddr; - assign m_axi_awlen = s_axi_awlen; - assign m_axi_awsize = s_axi_awsize; - assign m_axi_awburst = s_axi_awburst; - assign m_axi_awlock = s_axi_awlock; - assign m_axi_awcache = s_axi_awcache; - assign m_axi_awprot = s_axi_awprot; - assign m_axi_awqos = s_axi_awqos; - assign m_axi_awregion = s_axi_awregion; - assign m_axi_awuser = AWUSER_ENABLE ? s_axi_awuser : {AWUSER_WIDTH{1'b0}}; - assign m_axi_awvalid = s_axi_awvalid; - assign s_axi_awready = m_axi_awready; - -end - -// W channel - -if (W_REG_TYPE > 1) begin -// skid buffer, no bubble cycles - -// datapath registers -reg s_axi_wready_reg = 1'b0; - -reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; -reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; -reg m_axi_wlast_reg = 1'b0; -reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = {WUSER_WIDTH{1'b0}}; -reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next; - -reg [DATA_WIDTH-1:0] temp_m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; -reg [STRB_WIDTH-1:0] temp_m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; -reg temp_m_axi_wlast_reg = 1'b0; -reg [WUSER_WIDTH-1:0] temp_m_axi_wuser_reg = {WUSER_WIDTH{1'b0}}; -reg temp_m_axi_wvalid_reg = 1'b0, temp_m_axi_wvalid_next; - -// datapath control -reg store_axi_w_input_to_output; -reg store_axi_w_input_to_temp; -reg store_axi_w_temp_to_output; - -assign s_axi_wready = s_axi_wready_reg; - -assign m_axi_wdata = m_axi_wdata_reg; -assign m_axi_wstrb = m_axi_wstrb_reg; -assign m_axi_wlast = m_axi_wlast_reg; -assign m_axi_wuser = WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}}; -assign m_axi_wvalid = m_axi_wvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -wire s_axi_wready_early = m_axi_wready | (~temp_m_axi_wvalid_reg & (~m_axi_wvalid_reg | ~s_axi_wvalid)); - -always @* begin - // transfer sink ready state to source - m_axi_wvalid_next = m_axi_wvalid_reg; - temp_m_axi_wvalid_next = temp_m_axi_wvalid_reg; - - store_axi_w_input_to_output = 1'b0; - store_axi_w_input_to_temp = 1'b0; - store_axi_w_temp_to_output = 1'b0; - - if (s_axi_wready_reg) begin - // input is ready - if (m_axi_wready | ~m_axi_wvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axi_wvalid_next = s_axi_wvalid; - store_axi_w_input_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axi_wvalid_next = s_axi_wvalid; - store_axi_w_input_to_temp = 1'b1; - end - end else if (m_axi_wready) begin - // input is not ready, but output is ready - m_axi_wvalid_next = temp_m_axi_wvalid_reg; - temp_m_axi_wvalid_next = 1'b0; - store_axi_w_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_wready_reg <= 1'b0; - m_axi_wvalid_reg <= 1'b0; - temp_m_axi_wvalid_reg <= 1'b0; - end else begin - s_axi_wready_reg <= s_axi_wready_early; - m_axi_wvalid_reg <= m_axi_wvalid_next; - temp_m_axi_wvalid_reg <= temp_m_axi_wvalid_next; - end - - // datapath - if (store_axi_w_input_to_output) begin - m_axi_wdata_reg <= s_axi_wdata; - m_axi_wstrb_reg <= s_axi_wstrb; - m_axi_wlast_reg <= s_axi_wlast; - m_axi_wuser_reg <= s_axi_wuser; - end else if (store_axi_w_temp_to_output) begin - m_axi_wdata_reg <= temp_m_axi_wdata_reg; - m_axi_wstrb_reg <= temp_m_axi_wstrb_reg; - m_axi_wlast_reg <= temp_m_axi_wlast_reg; - m_axi_wuser_reg <= temp_m_axi_wuser_reg; - end - - if (store_axi_w_input_to_temp) begin - temp_m_axi_wdata_reg <= s_axi_wdata; - temp_m_axi_wstrb_reg <= s_axi_wstrb; - temp_m_axi_wlast_reg <= s_axi_wlast; - temp_m_axi_wuser_reg <= s_axi_wuser; - end -end - -end else if (W_REG_TYPE == 1) begin -// simple register, inserts bubble cycles - -// datapath registers -reg s_axi_wready_reg = 1'b0; - -reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}}; -reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}}; -reg m_axi_wlast_reg = 1'b0; -reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = {WUSER_WIDTH{1'b0}}; -reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next; - -// datapath control -reg store_axi_w_input_to_output; - -assign s_axi_wready = s_axi_wready_reg; - -assign m_axi_wdata = m_axi_wdata_reg; -assign m_axi_wstrb = m_axi_wstrb_reg; -assign m_axi_wlast = m_axi_wlast_reg; -assign m_axi_wuser = WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}}; -assign m_axi_wvalid = m_axi_wvalid_reg; - -// enable ready input next cycle if output buffer will be empty -wire s_axi_wready_ewly = !m_axi_wvalid_next; - -always @* begin - // transfer sink ready state to source - m_axi_wvalid_next = m_axi_wvalid_reg; - - store_axi_w_input_to_output = 1'b0; - - if (s_axi_wready_reg) begin - m_axi_wvalid_next = s_axi_wvalid; - store_axi_w_input_to_output = 1'b1; - end else if (m_axi_wready) begin - m_axi_wvalid_next = 1'b0; - end -end - -always @(posedge clk) begin - if (rst) begin - s_axi_wready_reg <= 1'b0; - m_axi_wvalid_reg <= 1'b0; - end else begin - s_axi_wready_reg <= s_axi_wready_ewly; - m_axi_wvalid_reg <= m_axi_wvalid_next; - end - - // datapath - if (store_axi_w_input_to_output) begin - m_axi_wdata_reg <= s_axi_wdata; - m_axi_wstrb_reg <= s_axi_wstrb; - m_axi_wlast_reg <= s_axi_wlast; - m_axi_wuser_reg <= s_axi_wuser; - end -end - -end else begin - - // bypass W channel - assign m_axi_wdata = s_axi_wdata; - assign m_axi_wstrb = s_axi_wstrb; - assign m_axi_wlast = s_axi_wlast; - assign m_axi_wuser = WUSER_ENABLE ? s_axi_wuser : {WUSER_WIDTH{1'b0}}; - assign m_axi_wvalid = s_axi_wvalid; - assign s_axi_wready = m_axi_wready; - -end - -// B channel - -if (B_REG_TYPE > 1) begin -// skid buffer, no bubble cycles - -// datapath registers -reg m_axi_bready_reg = 1'b0; - -reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}; -reg [1:0] s_axi_bresp_reg = 2'b0; -reg [BUSER_WIDTH-1:0] s_axi_buser_reg = {BUSER_WIDTH{1'b0}}; -reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next; - -reg [ID_WIDTH-1:0] temp_s_axi_bid_reg = {ID_WIDTH{1'b0}}; -reg [1:0] temp_s_axi_bresp_reg = 2'b0; -reg [BUSER_WIDTH-1:0] temp_s_axi_buser_reg = {BUSER_WIDTH{1'b0}}; -reg temp_s_axi_bvalid_reg = 1'b0, temp_s_axi_bvalid_next; - -// datapath control -reg store_axi_b_input_to_output; -reg store_axi_b_input_to_temp; -reg store_axi_b_temp_to_output; - -assign m_axi_bready = m_axi_bready_reg; - -assign s_axi_bid = s_axi_bid_reg; -assign s_axi_bresp = s_axi_bresp_reg; -assign s_axi_buser = BUSER_ENABLE ? s_axi_buser_reg : {BUSER_WIDTH{1'b0}}; -assign s_axi_bvalid = s_axi_bvalid_reg; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -wire m_axi_bready_early = s_axi_bready | (~temp_s_axi_bvalid_reg & (~s_axi_bvalid_reg | ~m_axi_bvalid)); - -always @* begin - // transfer sink ready state to source - s_axi_bvalid_next = s_axi_bvalid_reg; - temp_s_axi_bvalid_next = temp_s_axi_bvalid_reg; - - store_axi_b_input_to_output = 1'b0; - store_axi_b_input_to_temp = 1'b0; - store_axi_b_temp_to_output = 1'b0; - - if (m_axi_bready_reg) begin - // input is ready - if (s_axi_bready | ~s_axi_bvalid_reg) begin - // output is ready or currently not valid, transfer data to output - s_axi_bvalid_next = m_axi_bvalid; - store_axi_b_input_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_s_axi_bvalid_next = m_axi_bvalid; - store_axi_b_input_to_temp = 1'b1; - end - end else if (s_axi_bready) begin - // input is not ready, but output is ready - s_axi_bvalid_next = temp_s_axi_bvalid_reg; - temp_s_axi_bvalid_next = 1'b0; - store_axi_b_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - if (rst) begin - m_axi_bready_reg <= 1'b0; - s_axi_bvalid_reg <= 1'b0; - temp_s_axi_bvalid_reg <= 1'b0; - end else begin - m_axi_bready_reg <= m_axi_bready_early; - s_axi_bvalid_reg <= s_axi_bvalid_next; - temp_s_axi_bvalid_reg <= temp_s_axi_bvalid_next; - end - - // datapath - if (store_axi_b_input_to_output) begin - s_axi_bid_reg <= m_axi_bid; - s_axi_bresp_reg <= m_axi_bresp; - s_axi_buser_reg <= m_axi_buser; - end else if (store_axi_b_temp_to_output) begin - s_axi_bid_reg <= temp_s_axi_bid_reg; - s_axi_bresp_reg <= temp_s_axi_bresp_reg; - s_axi_buser_reg <= temp_s_axi_buser_reg; - end - - if (store_axi_b_input_to_temp) begin - temp_s_axi_bid_reg <= m_axi_bid; - temp_s_axi_bresp_reg <= m_axi_bresp; - temp_s_axi_buser_reg <= m_axi_buser; - end -end - -end else if (B_REG_TYPE == 1) begin -// simple register, inserts bubble cycles - -// datapath registers -reg m_axi_bready_reg = 1'b0; - -reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}; -reg [1:0] s_axi_bresp_reg = 2'b0; -reg [BUSER_WIDTH-1:0] s_axi_buser_reg = {BUSER_WIDTH{1'b0}}; -reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next; - -// datapath control -reg store_axi_b_input_to_output; - -assign m_axi_bready = m_axi_bready_reg; - -assign s_axi_bid = s_axi_bid_reg; -assign s_axi_bresp = s_axi_bresp_reg; -assign s_axi_buser = BUSER_ENABLE ? s_axi_buser_reg : {BUSER_WIDTH{1'b0}}; -assign s_axi_bvalid = s_axi_bvalid_reg; - -// enable ready input next cycle if output buffer will be empty -wire m_axi_bready_early = !s_axi_bvalid_next; - -always @* begin - // transfer sink ready state to source - s_axi_bvalid_next = s_axi_bvalid_reg; - - store_axi_b_input_to_output = 1'b0; - - if (m_axi_bready_reg) begin - s_axi_bvalid_next = m_axi_bvalid; - store_axi_b_input_to_output = 1'b1; - end else if (s_axi_bready) begin - s_axi_bvalid_next = 1'b0; - end -end - -always @(posedge clk) begin - if (rst) begin - m_axi_bready_reg <= 1'b0; - s_axi_bvalid_reg <= 1'b0; - end else begin - m_axi_bready_reg <= m_axi_bready_early; - s_axi_bvalid_reg <= s_axi_bvalid_next; - end - - // datapath - if (store_axi_b_input_to_output) begin - s_axi_bid_reg <= m_axi_bid; - s_axi_bresp_reg <= m_axi_bresp; - s_axi_buser_reg <= m_axi_buser; - end -end - -end else begin - - // bypass B channel - assign s_axi_bid = m_axi_bid; - assign s_axi_bresp = m_axi_bresp; - assign s_axi_buser = BUSER_ENABLE ? m_axi_buser : {BUSER_WIDTH{1'b0}}; - assign s_axi_bvalid = m_axi_bvalid; - assign m_axi_bready = s_axi_bready; - -end - -endgenerate - -endmodule - -`resetall diff --git a/xls/modules/zstd/external/priority_encoder.v b/xls/modules/zstd/external/priority_encoder.v deleted file mode 100644 index cf82512ba8..0000000000 --- a/xls/modules/zstd/external/priority_encoder.v +++ /dev/null @@ -1,92 +0,0 @@ -/* - -Copyright (c) 2014-2021 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`timescale 1ns / 1ps -`default_nettype none - -/* - * Priority encoder module - */ -module priority_encoder # -( - parameter WIDTH = 4, - // LSB priority selection - parameter LSB_HIGH_PRIORITY = 0 -) -( - input wire [WIDTH-1:0] input_unencoded, - output wire output_valid, - output wire [$clog2(WIDTH)-1:0] output_encoded, - output wire [WIDTH-1:0] output_unencoded -); - -parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1; -parameter W = 2**LEVELS; - -// pad input to even power of two -wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded}; - -wire [W/2-1:0] stage_valid[LEVELS-1:0]; -wire [W/2-1:0] stage_enc[LEVELS-1:0]; - -generate - genvar l, n; - - // process input bits; generate valid bit and encoded bit for each pair - for (n = 0; n < W/2; n = n + 1) begin : loop_in - assign stage_valid[0][n] = |input_padded[n*2+1:n*2]; - if (LSB_HIGH_PRIORITY) begin - // bit 0 is highest priority - assign stage_enc[0][n] = !input_padded[n*2+0]; - end else begin - // bit 0 is lowest priority - assign stage_enc[0][n] = input_padded[n*2+1]; - end - end - - // compress down to single valid bit and encoded bus - for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels - for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress - assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2]; - if (LSB_HIGH_PRIORITY) begin - // bit 0 is highest priority - assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]}; - end else begin - // bit 0 is lowest priority - assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]}; - end - end - end -endgenerate - -assign output_valid = stage_valid[LEVELS-1]; -assign output_encoded = stage_enc[LEVELS-1]; -assign output_unencoded = 1 << output_encoded; - -endmodule - -`resetall diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index 8985397377..1bf439c728 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -1696,15 +1696,15 @@ async def zstd_compressed_frames_test(dut): modified_zstd_verilog.name, "xls/modules/zstd/rtl/xls_fifo_wrapper.sv", "xls/modules/zstd/rtl/zstd_dec_wrapper.sv", - "xls/modules/zstd/external/axi_crossbar_wrapper.v", - "xls/modules/zstd/external/axi_crossbar.v", - "xls/modules/zstd/external/axi_crossbar_rd.v", - "xls/modules/zstd/external/axi_crossbar_wr.v", - "xls/modules/zstd/external/axi_crossbar_addr.v", - "xls/modules/zstd/external/axi_register_rd.v", - "xls/modules/zstd/external/axi_register_wr.v", - "xls/modules/zstd/external/arbiter.v", - "xls/modules/zstd/external/priority_encoder.v", + "xls/modules/zstd/axi_crossbar_wrapper.v", + "external/com_github_alexforencich_verilog_axi/rtl/axi_crossbar.v", + "external/com_github_alexforencich_verilog_axi/rtl/axi_crossbar_rd.v", + "external/com_github_alexforencich_verilog_axi/rtl/axi_crossbar_wr.v", + "external/com_github_alexforencich_verilog_axi/rtl/axi_crossbar_addr.v", + "external/com_github_alexforencich_verilog_axi/rtl/axi_register_rd.v", + "external/com_github_alexforencich_verilog_axi/rtl/axi_register_wr.v", + "external/com_github_alexforencich_verilog_axi/rtl/arbiter.v", + "external/com_github_alexforencich_verilog_axi/rtl/priority_encoder.v", "xls/modules/zstd/rtl/ram_1r1w.v", ] From ba76f0f259844ca17299df361f98700b6b165228 Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Wed, 23 Jul 2025 20:33:08 +0200 Subject: [PATCH 23/30] Downgrade dependencies Signed-off-by: Robert Winkler --- dependency_support/pip_requirements.in | 3 +- dependency_support/pip_requirements_lock.txt | 85 +++++++------------ xls/modules/zstd/BUILD | 8 -- xls/modules/zstd/cocotb/utils.py | 38 ++++++--- xls/modules/zstd/memory/BUILD | 8 -- .../zstd/memory/axi_writer_cocotb_test.py | 17 ++-- .../zstd/memory/mem_writer_cocotb_test.py | 17 ++-- xls/modules/zstd/rtl/zstd_dec_wrapper.sv | 6 +- xls/modules/zstd/zstd_dec_cocotb_test.py | 5 +- 9 files changed, 88 insertions(+), 99 deletions(-) diff --git a/dependency_support/pip_requirements.in b/dependency_support/pip_requirements.in index 683f77261d..3c765d7431 100644 --- a/dependency_support/pip_requirements.in +++ b/dependency_support/pip_requirements.in @@ -13,8 +13,7 @@ pyyaml==6.0.1 # We build most of z3 ourselves but building python is really complicated. Just # use pypi version z3-solver==4.14.0.0 -pytest==8.2.2 -cocotb==1.9.0 +cocotb==1.7.2 cocotbext-axi==0.1.24 cocotb_bus==0.2.1 zstandard==0.23.0 diff --git a/dependency_support/pip_requirements_lock.txt b/dependency_support/pip_requirements_lock.txt index b3f361a2a0..86f4386d60 100644 --- a/dependency_support/pip_requirements_lock.txt +++ b/dependency_support/pip_requirements_lock.txt @@ -14,43 +14,38 @@ click==8.1.3 \ # via # -r dependency_support/pip_requirements.in # flask -cocotb==1.9.0 \ - --hash=sha256:02a58ef6c941114964096e7c039bdd4e67e63816cfd2f6a9af6a34cd92b00e8e \ - --hash=sha256:0819794ef5e8fd14fee0b265933226cf600e85edc2f1a749b4d5f8fa2d31ce4e \ - --hash=sha256:0ba35617a677ff65a1273411a3dfdfc5f587128ad8cb9e941ab0eb17ec8fb3e2 \ - --hash=sha256:17556e3a23562f64d577d0eb117fe02e384aedee997b29497b5c395f5010ff82 \ - --hash=sha256:19b4e27b53a16e0b9c4cc5227c7f9d4dccac06e431a4f937e9f5513350196333 \ - --hash=sha256:1a0381ced5590a726032ba2265c6b70ac12cfb49edb152be86a081bb7d104751 \ - --hash=sha256:1aff68cf77059448a9a3278079037e34b50c8c2aee466d984295fa7fe699d390 \ - --hash=sha256:277281420fd6fc3002bb85d6bec497bd20ff3a3905d4b5f1301faf975f750ede \ - --hash=sha256:2daf743320331615f4e8ffb877ab0b04e6f913b911bb11bf9dbc1d876d9c4220 \ - --hash=sha256:2e9bcdbfba3e99c9297bd0d74ba781772d89d2c86e893980784ada252bd1a0f8 \ - --hash=sha256:3058c977f9d4e1f6333d505947f34b9142910719f1d8631c40a151dd86bad727 \ - --hash=sha256:5832d894419a9e8fe5c242e3ac86588e16e2cb379822dcb154bfec8544ae858e \ - --hash=sha256:598b841ed0809e5c64d8c383b8035f6ace5a6f9013f680cdc6981221911c005d \ - --hash=sha256:5a5c91027d7652aaf10e101743edd6b1e832039a19af75fca301275ef30f01d4 \ - --hash=sha256:61418f619af72c8cca8de622785b4f4bfc17ace09981de6eb44feae560cf3bbb \ - --hash=sha256:784c914c8df3fd79cfb148d2bcd17c4b2703c89af1278ed98773afb57ceea3e6 \ - --hash=sha256:87a19d3012f505ba7fda37483b851ef0ca40290ad8a9b28a820b84f8574287bb \ - --hash=sha256:89503f0749362d36b6fab8636710f1848943c21f9d488672921bac21e9edd29f \ - --hash=sha256:89e5189fd393918c27af2daefdcb13df4d52fa761f065d5964d2c4ff5c0642fb \ - --hash=sha256:8cb4b0edf8f0b47c3b604b461cb574fc75fd97efa893cbaf828f4f2f71cf459e \ - --hash=sha256:94e884e16186899ad5b4d131c3f7ff0a2277e67ea0660754e8810a4bbf2d610e \ - --hash=sha256:997dbca2a2cd933fd0a44d9fadeebc1e8a40701db15ea06f207811933dceb350 \ - --hash=sha256:a7cea13cb2fe4f5ca735490846342885117778a73008a67ed9cac667aaaf3f0d \ - --hash=sha256:a84edfbfa57dc6e16845a55feb0b4e1c8b6bbfa5ef1ab6768beba8d81e0546aa \ - --hash=sha256:a95b5e5708a3629d319d2b655d11345cc7e97fea9bdc9bc1df7435926ac30966 \ - --hash=sha256:aa6818c39ca1ce699e4bb1d84899c4f98c2d25c7671bd6c7beee3b1ee9d68834 \ - --hash=sha256:ab99bf7e055780b57419d4133fd4dca9c72a03b766a3e2200552f10498eb8845 \ - --hash=sha256:b966f5560a494fd99f95a1562f9326ca20c35bb118d4e6b50db41da8e4a6f718 \ - --hash=sha256:bc44a7708a5a63d3059a622c2fb90831dc33534c3343e971f5a6c78905097baa \ - --hash=sha256:c11e21d291ba2f889e33c21d76e9aec6ffdfb5666053dc34452666579daa675b \ - --hash=sha256:c848de13583478d71cc91e528e17c051ca6a3b92e89d703ac5015f17cab1287b \ - --hash=sha256:d944aa5509a0f0786d6f30554a2f8b1f229847f9ac9988879d7a05497739f668 \ - --hash=sha256:f50862153e1364f6edeaef9d70505093549fa097e9b2555ea46d1e4f94ac3287 \ - --hash=sha256:f74c598e230e1035103f6e3a97dd7a0e1bcacf7f3ea7481cd3bcde477b74e379 \ - --hash=sha256:fcb81c6c37e11b0729768dd8e192a9cfb809778699ab1fe89f4d92ba0beb3092 \ - --hash=sha256:ff2ddc8b304eb7076ceead2534a1b9828df771798fa9c2601ea983c86d23ec08 +cocotb==1.7.2 \ + --hash=sha256:0c1687ac78141724b8529e029ee6299698ecaa8a2c431b744eeff487a4bb18de \ + --hash=sha256:163e5262020cc21f6a0391fb4727c9ab3ecbf6ee12a1472c8f7320b3ba211a50 \ + --hash=sha256:170cf4d01c4d7c6c5b141ffc1824e846a6c8adbed553a50984cd522c1dddb111 \ + --hash=sha256:1851ac56eed7bb6c745aabfc0e417195cb4f08b5df50846c04eb77a868bfeaba \ + --hash=sha256:1abffb36183b07469c490836c66d8b9e24fc1bec7c27356818618a6719fabd4b \ + --hash=sha256:33be79f048f4072240668a079d2bcebd1a24611a0a1e55439b65ffa0ff077790 \ + --hash=sha256:34ab1bf3f18476724dd4e21dbcc0e060e813eb502abe155b800084fb6945360c \ + --hash=sha256:360019f74270661d14e9caa8103e740a070cb466ab08376a565ec0ef4c13dbbf \ + --hash=sha256:37ddb79f4ab60d2d2dc5a9db5bf767d226eb4978fd15b84dfb968d31ab2fcda5 \ + --hash=sha256:43f5af578803e5726b5c75421c0e35e54021ab423d3aa4efe930feb740d6479d \ + --hash=sha256:4738f36b9730cc05b74ccba3648dba0455cf9f237abf822ef307a274a29474c2 \ + --hash=sha256:4aa5d73ebdb59ef24cef36a1f8cca11dcecb3ee7b71a84df02751020bc67ea77 \ + --hash=sha256:574d21501ff1a3d36889397cd58a18d102d0e40391aa7a0274b600d1cc4c7dc3 \ + --hash=sha256:69f4e539dd308c9e169ab23135138ec397061b700f209803a6022ae9fbe08933 \ + --hash=sha256:6f289ac00f4884046ec64db7006e47b1c857a36dcd2a80ea0873cbff00248368 \ + --hash=sha256:707f795a17679b4653a50bd4094536a46fbfee5c6e3d951fac4320ee211ad13f \ + --hash=sha256:7828e22946f128aa59cb9254de4037b99e3bd5a51fe8f590cf64a3141d742a37 \ + --hash=sha256:82f694da656a699154b15ee28be3ac39c41a71d33985313deda12a3645f8b3db \ + --hash=sha256:959892eb94bd0b3ff40e0fca51d33a3936416deb853e2bac4f7f766b40002650 \ + --hash=sha256:a7ec6a2d212c27ec46bed17a15d60b7b29cd0f734f11cc16d2cb4d3f6136e133 \ + --hash=sha256:a90c77f4bbfdf73aa16093dfe95c68af1a1ca685ebfa525f3f150eab252f6728 \ + --hash=sha256:b288a59fa8dffc1cbc53105e71e2f8c82421081b17282e41319832654b309477 \ + --hash=sha256:c41cc8d4ece57f5e26076cd12f1e11d464d7f118fdb74b958269535185d99a30 \ + --hash=sha256:c8dce91d2a918ee63338d79b08e3d52f1d2797efd9c2bedd13c33d674f730db8 \ + --hash=sha256:d26a8a40cea61f295be04b1164a5dd9ec873f13a39814ad00efec7fd899320e0 \ + --hash=sha256:d80b3baafff1a8a91ac860023c448c603767bed502258160a5cb6029976fec4f \ + --hash=sha256:dcf5354268f16d9e11e05cf3616172ca5ef503b45567f75ebd96a0bfdb9832d1 \ + --hash=sha256:ded849360fb31746f1ba3a994f89c3bba2466ec2d0b4b5da0030645645f938d4 \ + --hash=sha256:e03df73573aec261447602904bd66927eeb2f00dd24370dc9a57f47fd42c4d70 \ + --hash=sha256:f97c2eb92cb68831f19b82ba0038ce40fa73c5edbffb7930745edac20c5358d1 \ + --hash=sha256:fa8abed5260baf4306fbfb997c8789fe24bc229cd762b12d7dba0b9c20147b1d # via # -r dependency_support/pip_requirements.in # cocotb-bus @@ -184,10 +179,6 @@ fonttools==4.55.8 \ --hash=sha256:f089e8da0990cfe2d67e81d9cf581ff372b48dc5acf2782701844211cd1f0eb3 \ --hash=sha256:f971aa5f50c22dc4b63a891503624ae2c77330429b34ead32f23c2260c5618cd # via matplotlib -iniconfig==2.0.0 \ - --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ - --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 - # via pytest itsdangerous==2.1.2 \ --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a @@ -404,9 +395,7 @@ numpy==1.24.4 \ packaging==24.2 \ --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f - # via - # matplotlib - # pytest + # via matplotlib pillow==11.1.0 \ --hash=sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83 \ --hash=sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96 \ @@ -480,10 +469,6 @@ pillow==11.1.0 \ --hash=sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9 \ --hash=sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761 # via matplotlib -pluggy==1.5.0 \ - --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ - --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 - # via pytest portpicker==1.3.1 \ --hash=sha256:d2cdc776873635ed421315c4d22e63280042456bbfa07397817e687b142b9667 # via -r dependency_support/pip_requirements.in @@ -504,10 +489,6 @@ pyparsing==3.2.1 \ --hash=sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1 \ --hash=sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a # via matplotlib -pytest==8.2.2 \ - --hash=sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343 \ - --hash=sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977 - # via -r dependency_support/pip_requirements.in python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index eb4e7cf9a6..a1a233e1b6 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -1854,17 +1854,11 @@ py_test( "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], - env = { - "BUILD_WORKING_DIRECTORY": "sim_build", - "PYTHONUNBUFFERED": "1", - }, - imports = ["."], tags = ["manual"], visibility = ["//xls:xls_users"], deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("pytest"), requirement("zstandard"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", @@ -2311,7 +2305,6 @@ py_test( "@com_icarus_iverilog//:vvp", ], env = { - "BUILD_WORKING_DIRECTORY": "sim_build", "PYTHONUNBUFFERED": "1", }, imports = ["."], @@ -2320,7 +2313,6 @@ py_test( deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("pytest"), requirement("zstandard"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", diff --git a/xls/modules/zstd/cocotb/utils.py b/xls/modules/zstd/cocotb/utils.py index 01688f96a3..43f9ca16bc 100644 --- a/xls/modules/zstd/cocotb/utils.py +++ b/xls/modules/zstd/cocotb/utils.py @@ -34,27 +34,45 @@ def setup_com_iverilog(): ) os.environ["PATH"] += os.pathsep + str(iverilog_path.parent) os.environ["PATH"] += os.pathsep + str(vvp_path.parent) - build_dir = pathlib.Path(os.environ['BUILD_WORKING_DIRECTORY'], "sim_build") + build_dir = pathlib.Path("sim_build").absolute() return build_dir -def run_test(toplevel, test_module, verilog_sources): + +def run_test(toplevel, test_module, verilog_sources, timescale=("1ns", "1ps")): """Builds and runs a Cocotb testbench using Icarus Verilog.""" build_dir = setup_com_iverilog() - runner = get_runner("icarus") + runner = get_runner("icarus")() + build_args = [] + + cmds_file = build_dir / pathlib.Path("cmds.f") + cmds_file.parent.mkdir(parents=True, exist_ok=True) + with open(cmds_file, "w") as f: + f.write("+timescale+{}/{}\n".format(*timescale)) + build_args += ["-f", str(cmds_file)] + + dump_file = build_dir / pathlib.Path("cocotb_iverilog_dump.v") + wave_file = build_dir / pathlib.Path(f"{toplevel}.fst") + with open(dump_file, "w") as f: + f.write("module cocotb_iverilog_dump();\n") + f.write("initial begin\n") + f.write(f' $dumpfile("{wave_file}");\n') + f.write(f" $dumpvars(0, {toplevel});\n") + f.write("end\n") + f.write("endmodule\n") + wave_file.parent.mkdir(parents=True, exist_ok=True) + runner.build( - verilog_sources=verilog_sources, - hdl_toplevel=toplevel, - timescale=("1ns", "1ps"), + verilog_sources=(verilog_sources + [str(dump_file)]), + toplevel=toplevel, build_dir=build_dir, + extra_args=build_args, defines={"SIMULATION": "1"}, - waves=True, ) try: results_xml = runner.test( - hdl_toplevel=toplevel, - test_module=test_module, - waves=True, + toplevel=toplevel, + py_module=test_module, ) finally: check_results_file(results_xml) diff --git a/xls/modules/zstd/memory/BUILD b/xls/modules/zstd/memory/BUILD index 461b3518e4..b0d7312393 100644 --- a/xls/modules/zstd/memory/BUILD +++ b/xls/modules/zstd/memory/BUILD @@ -557,13 +557,11 @@ py_test( "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], - env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, tags = ["manual"], visibility = ["//xls:xls_users"], deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("pytest"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", "//xls/modules/zstd/cocotb:memory", @@ -653,14 +651,11 @@ py_test( "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], - env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, - imports = ["."], tags = ["manual"], visibility = ["//xls:xls_users"], deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("pytest"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", "//xls/modules/zstd/cocotb:utils", @@ -819,14 +814,11 @@ py_test( "@com_icarus_iverilog//:iverilog", "@com_icarus_iverilog//:vvp", ], - env = {"BUILD_WORKING_DIRECTORY": "sim_build"}, - imports = ["."], tags = ["manual"], visibility = ["//xls:xls_users"], deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("pytest"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", "//xls/modules/zstd/cocotb:utils", diff --git a/xls/modules/zstd/memory/axi_writer_cocotb_test.py b/xls/modules/zstd/memory/axi_writer_cocotb_test.py index 2ad396c3c6..270a390416 100644 --- a/xls/modules/zstd/memory/axi_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/axi_writer_cocotb_test.py @@ -16,6 +16,7 @@ import random import logging import pathlib +import sys import cocotb from cocotb.clock import Clock @@ -300,10 +301,12 @@ def generate_test_data_arbitrary(mem_size): ) if __name__ == "__main__": - toplevel = "axi_writer_wrapper" - verilog_sources = [ - "xls/modules/zstd/memory/axi_writer.v", - "xls/modules/zstd/memory/rtl/axi_writer_wrapper.v", - ] - test_module=[pathlib.Path(__file__).stem] - utils.run_test(toplevel, test_module, verilog_sources) + sys.path.append(str(pathlib.Path(__file__).parent)) + + toplevel = "axi_writer_wrapper" + verilog_sources = [ + "xls/modules/zstd/memory/axi_writer.v", + "xls/modules/zstd/memory/rtl/axi_writer_wrapper.v", + ] + test_module=[pathlib.Path(__file__).stem] + utils.run_test(toplevel, test_module, verilog_sources) diff --git a/xls/modules/zstd/memory/mem_writer_cocotb_test.py b/xls/modules/zstd/memory/mem_writer_cocotb_test.py index 5767fbba2e..a74a5db2e7 100644 --- a/xls/modules/zstd/memory/mem_writer_cocotb_test.py +++ b/xls/modules/zstd/memory/mem_writer_cocotb_test.py @@ -17,6 +17,7 @@ import logging import enum import pathlib +import sys import cocotb from cocotb.clock import Clock @@ -717,13 +718,15 @@ def generate_padded_test_data_arbitrary(mem_size, test_cases): ) if __name__ == "__main__": - toplevel = "mem_writer_wrapper" - verilog_sources = [ - "xls/modules/zstd/memory/mem_writer.v", - "xls/modules/zstd/memory/rtl/mem_writer_wrapper.v", - ] - test_module=[pathlib.Path(__file__).stem] - utils.run_test(toplevel, test_module, verilog_sources) + sys.path.append(str(pathlib.Path(__file__).parent)) + + toplevel = "mem_writer_wrapper" + verilog_sources = [ + "xls/modules/zstd/memory/mem_writer.v", + "xls/modules/zstd/memory/rtl/mem_writer_wrapper.v", + ] + test_module=[pathlib.Path(__file__).stem] + utils.run_test(toplevel, test_module, verilog_sources) test_cases_single_burst_1_transfer = [ # Aligned Address; Aligned Length diff --git a/xls/modules/zstd/rtl/zstd_dec_wrapper.sv b/xls/modules/zstd/rtl/zstd_dec_wrapper.sv index 36029c7917..79a6199810 100644 --- a/xls/modules/zstd/rtl/zstd_dec_wrapper.sv +++ b/xls/modules/zstd/rtl/zstd_dec_wrapper.sv @@ -1304,7 +1304,7 @@ module zstd_dec_wrapper #( .SIZE(256), .NUM_PARTITIONS(1), .ADDR_WIDTH(15), - .INIT_FILE("../../xls/modules/zstd/zstd_dec_ll_fse_default.mem") + .INIT_FILE("../xls/modules/zstd/zstd_dec_ll_fse_default.mem") ) ll_def_fse_ram ( .clk(clk), .rst(rst), @@ -1361,7 +1361,7 @@ module zstd_dec_wrapper #( .SIZE(256), .NUM_PARTITIONS(1), .ADDR_WIDTH(15), - .INIT_FILE("../../xls/modules/zstd/zstd_dec_ml_fse_default.mem") + .INIT_FILE("../xls/modules/zstd/zstd_dec_ml_fse_default.mem") ) ml_def_fse_ram ( .clk(clk), .rst(rst), @@ -1418,7 +1418,7 @@ module zstd_dec_wrapper #( .SIZE(256), .NUM_PARTITIONS(1), .ADDR_WIDTH(15), - .INIT_FILE("../../xls/modules/zstd/zstd_dec_of_fse_default.mem") + .INIT_FILE("../xls/modules/zstd/zstd_dec_of_fse_default.mem") ) of_def_fse_ram ( .clk(clk), .rst(rst), diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index 1bf439c728..e212265fc9 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - +import sys import enum import pathlib import tempfile @@ -550,7 +550,7 @@ async def zstd_rle_frames_test(dut): # Use them to verify progress in specific parts of the decoder. # TODO the workdir / data relation is weird. How to pass this better? -PREGENERATED_FILES_DIR = "../../xls/modules/zstd/data/" +PREGENERATED_FILES_DIR = "../xls/modules/zstd/data/" @cocotb.test(timeout_time=2000, timeout_unit="ms") @@ -1689,6 +1689,7 @@ async def zstd_compressed_frames_test(dut): # await testing_routine(dut, test_cases, block_type) if __name__ == "__main__": + sys.path.append(str(pathlib.Path(__file__).parent)) with tempfile.NamedTemporaryFile(mode="w") as modified_zstd_verilog: toplevel = "zstd_dec_wrapper" test_module = [pathlib.Path(__file__).stem] From 63b47c2360ab34bb984eff42bce277a95d179589 Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Thu, 24 Jul 2025 16:49:36 +0200 Subject: [PATCH 24/30] Run tests selectively in GitHub CI Signed-off-by: Robert Winkler --- .github/workflows/modules-zstd.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/modules-zstd.yml b/.github/workflows/modules-zstd.yml index 4272e4b91b..bdf61906f5 100644 --- a/.github/workflows/modules-zstd.yml +++ b/.github/workflows/modules-zstd.yml @@ -45,7 +45,9 @@ jobs: - name: Test ZSTD Module - DSLX Tests (opt) if: ${{ !cancelled() }} run: | - bazel test -c opt --test_output=errors -- $(bazel query 'filter("_dslx_test$", kind(rule, //xls/modules/zstd/...))') + bazel test -c opt --test_output=errors -- $(bazel query 'filter("_dslx_test$", kind(rule, //xls/modules/zstd/...)) except filter("zstd_dec_dslx_test$", kind(rule, //xls/modules/zstd/...))'); + # Run all tests except those ending with `_skip` + bazel test -c opt --test_strategy=exclusive --test_output=errors --test_filter='^(.*[^_]|.*_[^s]|.*_s[^k]|.*_sk[^i]|.*_ski[^p])$' //xls/modules/zstd:zstd_dec_dslx_test; - name: Build ZSTD verilog targets (opt) if: ${{ !cancelled() }} From 05e77f72cfe928d260c47add937d7c30055f14ef Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Fri, 25 Jul 2025 16:19:06 +0200 Subject: [PATCH 25/30] Remove zstandard python library Signed-off-by: Robert Winkler --- dependency_support/pip_requirements.in | 1 - dependency_support/pip_requirements_lock.txt | 99 -------------------- xls/modules/zstd/BUILD | 3 - xls/modules/zstd/cocotb/BUILD | 1 + xls/modules/zstd/cocotb/data_generator.py | 14 ++- 5 files changed, 12 insertions(+), 106 deletions(-) diff --git a/dependency_support/pip_requirements.in b/dependency_support/pip_requirements.in index 3c765d7431..51ced9d019 100644 --- a/dependency_support/pip_requirements.in +++ b/dependency_support/pip_requirements.in @@ -16,7 +16,6 @@ z3-solver==4.14.0.0 cocotb==1.7.2 cocotbext-axi==0.1.24 cocotb_bus==0.2.1 -zstandard==0.23.0 # Note: numpy and scipy version availability seems to differ between Ubuntu # versions that we want to support (e.g. 18.04 vs 20.04), so we accept a diff --git a/dependency_support/pip_requirements_lock.txt b/dependency_support/pip_requirements_lock.txt index 86f4386d60..fc650abd8b 100644 --- a/dependency_support/pip_requirements_lock.txt +++ b/dependency_support/pip_requirements_lock.txt @@ -590,102 +590,3 @@ z3-solver==4.14.0.0 \ --hash=sha256:c10f899c6a876e3a50e9b2c4927604c2c3da3cca672b8ed3b7db1bc97259e47f \ --hash=sha256:e6ae32bc1cf4d25b96f790755d790a23118e8a09b9b6060e32238fe6ff43606d # via -r dependency_support/pip_requirements.in -zstandard==0.23.0 \ - --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ - --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \ - --hash=sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15 \ - --hash=sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072 \ - --hash=sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4 \ - --hash=sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e \ - --hash=sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26 \ - --hash=sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8 \ - --hash=sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5 \ - --hash=sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd \ - --hash=sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c \ - --hash=sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db \ - --hash=sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5 \ - --hash=sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc \ - --hash=sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152 \ - --hash=sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269 \ - --hash=sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045 \ - --hash=sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e \ - --hash=sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d \ - --hash=sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a \ - --hash=sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb \ - --hash=sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740 \ - --hash=sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105 \ - --hash=sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274 \ - --hash=sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2 \ - --hash=sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58 \ - --hash=sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b \ - --hash=sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4 \ - --hash=sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db \ - --hash=sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e \ - --hash=sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9 \ - --hash=sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0 \ - --hash=sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813 \ - --hash=sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e \ - --hash=sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512 \ - --hash=sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 \ - --hash=sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b \ - --hash=sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48 \ - --hash=sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a \ - --hash=sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772 \ - --hash=sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed \ - --hash=sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373 \ - --hash=sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea \ - --hash=sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd \ - --hash=sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f \ - --hash=sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc \ - --hash=sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 \ - --hash=sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2 \ - --hash=sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db \ - --hash=sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70 \ - --hash=sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259 \ - --hash=sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9 \ - --hash=sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700 \ - --hash=sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003 \ - --hash=sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba \ - --hash=sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a \ - --hash=sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c \ - --hash=sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90 \ - --hash=sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690 \ - --hash=sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f \ - --hash=sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840 \ - --hash=sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d \ - --hash=sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9 \ - --hash=sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35 \ - --hash=sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd \ - --hash=sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a \ - --hash=sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea \ - --hash=sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1 \ - --hash=sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573 \ - --hash=sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09 \ - --hash=sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094 \ - --hash=sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78 \ - --hash=sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9 \ - --hash=sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5 \ - --hash=sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9 \ - --hash=sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391 \ - --hash=sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847 \ - --hash=sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2 \ - --hash=sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c \ - --hash=sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2 \ - --hash=sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057 \ - --hash=sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20 \ - --hash=sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d \ - --hash=sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4 \ - --hash=sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54 \ - --hash=sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171 \ - --hash=sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e \ - --hash=sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160 \ - --hash=sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b \ - --hash=sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58 \ - --hash=sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8 \ - --hash=sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33 \ - --hash=sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a \ - --hash=sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880 \ - --hash=sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca \ - --hash=sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b \ - --hash=sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69 - # via -r dependency_support/pip_requirements.in diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index a1a233e1b6..620d743f98 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -1454,7 +1454,6 @@ py_binary( tags = ["manual"], visibility = ["//xls:xls_users"], deps = [ - requirement("zstandard"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:data_generator", "@com_google_protobuf//:protobuf_python", @@ -1859,7 +1858,6 @@ py_test( deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("zstandard"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", "//xls/modules/zstd/cocotb:data_generator", @@ -2313,7 +2311,6 @@ py_test( deps = [ requirement("cocotb"), requirement("cocotbext-axi"), - requirement("zstandard"), "//xls/common:runfiles", "//xls/modules/zstd/cocotb:channel", "//xls/modules/zstd/cocotb:data_generator", diff --git a/xls/modules/zstd/cocotb/BUILD b/xls/modules/zstd/cocotb/BUILD index cdb788d732..6c08efa697 100644 --- a/xls/modules/zstd/cocotb/BUILD +++ b/xls/modules/zstd/cocotb/BUILD @@ -71,5 +71,6 @@ py_library( deps = [ "//xls/common:runfiles", "@zstd//:decodecorpus", + "@zstd//:zstd_cli", ], ) diff --git a/xls/modules/zstd/cocotb/data_generator.py b/xls/modules/zstd/cocotb/data_generator.py index 3c9233f6d6..d0c5cc0495 100644 --- a/xls/modules/zstd/cocotb/data_generator.py +++ b/xls/modules/zstd/cocotb/data_generator.py @@ -19,7 +19,7 @@ from xls.common import runfiles import subprocess -import zstandard +import tempfile class BlockType(enum.Enum): """Enum encoding of ZSTD block types.""" @@ -67,8 +67,16 @@ def CallDecodecorpus(args): subprocess.run(cmd_concat, shell=True, check=True) def DecompressFrame(data): - dctx = zstandard.ZstdDecompressor() - return dctx.decompress(data) + zstd_cli = pathlib.Path(runfiles.get_path("zstd_cli", repository = "zstd")) + with tempfile.NamedTemporaryFile(mode='wb') as input_data, \ + tempfile.NamedTemporaryFile(mode='wb') as output_data: + input_data.write(data) + input_data.flush() + cmd = f"{str(zstd_cli)} -f -d {input_data.name} -o {output_data.name}" + output_data.close() + subprocess.run(cmd, shell=True, check=True) + with open(output_data.name, "rb") as output_data: + return output_data.read() def GenerateFrame(seed, btype, output_path, ltype=LiteralType.RANDOM): args = [] From c748093b12ecfa5a207cabbc93c4a01e5404b072 Mon Sep 17 00:00:00 2001 From: Dominik Lau Date: Tue, 29 Jul 2025 09:25:11 +0200 Subject: [PATCH 26/30] modules: zstd: update readme --- xls/modules/zstd/README.md | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/xls/modules/zstd/README.md b/xls/modules/zstd/README.md index aae9a03c8c..c0785c1fc7 100644 --- a/xls/modules/zstd/README.md +++ b/xls/modules/zstd/README.md @@ -10,7 +10,7 @@ the diagram below. The decoder comprises: * Control and Status Registers, * Frame Header Decoder, * Block Header Decoder, -* 3 types of processing units: RAW-, RLE-, and Compressed Block Decoders[^1], +* 3 types of processing units: RAW-, RLE-, and Compressed Block Decoders, * Command Aggregator, The Decoder interacts with the environment through a set of ports: @@ -39,7 +39,7 @@ Once the decoding process is started, the decoder: updates the history, 7. Prepares the final output of the decoder and writes it to the memory, 8. (Optional) Calculates checksum and compares it against the checksum read - from the frame.[^2] + from the frame.[^1] ![brief data flow diagram of ZstdDecoder](img/ZSTD_decoder.png) @@ -220,7 +220,7 @@ processing request to the `RleBlockDecoder`. The proc produces `N*s` repeats of the given symbol. This step preserves the block ID and attaches the literals tag to all its outputs. -#### CompressedBlockDecoder[^1] +#### CompressedBlockDecoder This part of the design is responsible for decoding the compressed data blocks. It ingests the bytes stream, and internally translates and interprets incoming @@ -262,7 +262,7 @@ will show the following behavior, depending on the tag: * Copy `copy_length` literals starting `offset _length` from the newest in history buffer to the history buffer as the newest. -### Compressed block decoder architecture[^1] {#compressed-block-decoder-architecture1} +### Compressed block decoder architecture {#compressed-block-decoder-architecture1} This part of the design is responsible for processing the compressed blocks up to the `literals`/`copy` command sequence. This sequence is then processed by @@ -278,7 +278,7 @@ Treeless blocks. #### Compressed block dispatcher This proc parses literals section headers to calculate block compression format, -Huffmman tree size (if applicable based on compression format), compressed and +Huffman tree size (if applicable based on compression format), compressed and regenerated sizes for literals. If compressed block format is `Compressed_Literals_Block`, dispatcher reads Huffman tree header byte from Huffman bitstream, and directs expected number of bytes to the Huffman tree @@ -493,6 +493,8 @@ The Basic test case for the ZstdDecoder is composed of the following steps: 6. Test case succeeds once `Notify` is asserted, all expected data is received and the decoder lands in `IDLE` state with status `OKAY` in the `Status` CSR. +Additionally, pregenerated test cases are provided in the [data](data/) subdirectory. `*.zst` files contain frames encoded using the ZSTD library. Supplementary `*.log` files provide additional info regarding the contents of each frame. Among the aforementioned test cases, those generated using `decodecorpus` follow the `__seed_` naming convention. + ### Failure points #### User-facing decoder errors @@ -506,6 +508,10 @@ The design will fail the tests under the following conditions: results from the reference library * The decoding result from the simulation has different contents than the results from the reference library +* Failures caused by incorrect intermediate results (only in the selected tests): + * Incorrect decoding of the FSE table + * Incorrect Huffman weights + * Incorrect Huffman codebook Currently, all mentioned conditions lead to an eventual test failure. @@ -566,14 +572,6 @@ This is done for example in: * Frame header decoder * SequenceExecutor -### Testing against [libzstd](https://github.com/facebook/zstd) - -Design is verified by comparing decoding results to the reference library -`libzstd`. ZSTD frames used for testing are generated with -[decodecorpus](https://github.com/facebook/zstd/blob/dev/tests/decodecorpus.c) -utility. The generated frame is then decoded with `libzstd` and with simulated -`ZstdDecoder`. - #### Positive test cases If the results of decoding with `libzstd` are valid, the test runs the same @@ -618,5 +616,4 @@ The alternatives for writing negative tests include: then tweaking the raw bits in this frame to trigger the error response from the decoder -[^1]: `CompressedBlockDecoder` is to be added in follow-up PRs. -[^2]: Checksum verification is currently unsupported. +[^1]: Checksum verification is currently unsupported. From 98fb26d80a5fe5394abc3d9eba8d6bcea6450736 Mon Sep 17 00:00:00 2001 From: Robert Winkler Date: Sat, 19 Jul 2025 00:18:18 +0200 Subject: [PATCH 27/30] Add cocotb check for verifying huffman codes Signed-off-by: Robert Winkler --- xls/modules/zstd/huffman_decoder.x | 2 +- xls/modules/zstd/zstd_dec_cocotb_test.py | 293 ++++++++++++++++++++++- 2 files changed, 292 insertions(+), 3 deletions(-) diff --git a/xls/modules/zstd/huffman_decoder.x b/xls/modules/zstd/huffman_decoder.x index 5652a64da6..50895ac4e2 100644 --- a/xls/modules/zstd/huffman_decoder.x +++ b/xls/modules/zstd/huffman_decoder.x @@ -223,7 +223,7 @@ pub proc HuffmanDecoder { trace_fmt!("[HuffmanDecoder] Received codes:"); for (i, ()) in u32:0..SYMBOLS_N { if symbol_valid[i] { - trace_fmt!("[HuffmanDecoder] {:#b} (len {}) -> {:#x}", symbol_code[i], symbol_code_len[i], i); + trace_fmt!("[HuffmanDecoder] {:#x} (len {}) -> {:#x}", symbol_code[i], symbol_code_len[i], i); } else {}; }(()); FSM::READ_DATA diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index e212265fc9..f685ce4fc4 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -13,6 +13,7 @@ # limitations under the License. import sys +import math import enum import pathlib import tempfile @@ -93,6 +94,40 @@ class FseTableRecord(xlsstruct.XLSStruct): symbol: SYMBOL_W +PARALLEL_ACCESS_WIDTH = 8 +MAX_WEIGHT = 11 +WEIGHT_LOG = math.ceil(math.log2(MAX_WEIGHT + 1)) +VALID_W = 1 + + +@xlsstruct.xls_dataclass +class CodeBuilderOutput(xlsstruct.XLSStruct): + symbol_valid_7: VALID_W + symbol_valid_6: VALID_W + symbol_valid_5: VALID_W + symbol_valid_4: VALID_W + symbol_valid_3: VALID_W + symbol_valid_2: VALID_W + symbol_valid_1: VALID_W + symbol_valid_0: VALID_W + code_length_7: WEIGHT_LOG + code_length_6: WEIGHT_LOG + code_length_5: WEIGHT_LOG + code_length_4: WEIGHT_LOG + code_length_3: WEIGHT_LOG + code_length_2: WEIGHT_LOG + code_length_1: WEIGHT_LOG + code_length_0: WEIGHT_LOG + code_7: MAX_WEIGHT + code_6: MAX_WEIGHT + code_5: MAX_WEIGHT + code_4: MAX_WEIGHT + code_3: MAX_WEIGHT + code_2: MAX_WEIGHT + code_1: MAX_WEIGHT + code_0: MAX_WEIGHT + + class CSR(enum.Enum): """ Maps the offsets to the ZSTD Decoder registers. @@ -129,6 +164,10 @@ def print_ram_contents(mem, name="", size=None): print(f"{name} [{i}]\t: {hex(mem[i].value)}") +def fields_as_array(data, prefix, count): + return [getattr(data, f"{prefix}_{i}") for i in range(count)] + + def set_termination_event(monitor, event, transactions): def terminate_cb(_): if monitor.stats.received_transactions == transactions: @@ -375,6 +414,76 @@ def func(): cocotb.start_soon(get_handshake_event(dut, fse_lookup_resp_handshake, func)) +def reverse_expected_huffman_codes(exp_codes): + def reverse_bits(value, max_bits): + bv = BinaryValue(value=value, n_bits=max_bits, bigEndian=False) + return int(BinaryValue(value=bv.binstr[::-1], n_bits=max_bits, bigEndian=False)) + + max_bits = max(d["length"] for d in exp_codes) + + codes = [] + for record in exp_codes: + codes += [ + { + "code": reverse_bits(record["code"], max_bits), + "length": record["length"], + "symbol": record["symbol"], + } + ] + return codes + + +async def test_huffman_codes(dut, clock, expected_codes): + WEIGHT_CODE_BUILDER_INST = ( + dut.ZstdDecoder.xls_modules_zstd_huffman_code_builder__ZstdDecoderInst__ZstdDecoder_0__CompressBlockDecoder_0__LiteralsDecoder_0__HuffmanLiteralsDecoder_0__WeightCodeBuilder_0_next_inst19 + ) + CODES_CHANNEL_NAME = "zstd_dec__code_builder_codes" + + codes_channel = xlschannel.XLSChannel( + WEIGHT_CODE_BUILDER_INST, CODES_CHANNEL_NAME, dut.clk + ) + huffman_code_handshake = triggers.Event() + + codes = [] + block_cnt = 0 + packet_cnt = 0 + symbol_cnt = 0 + + def func(): + nonlocal codes + nonlocal symbol_cnt + nonlocal packet_cnt + nonlocal block_cnt + + assert block_cnt <= 32 + codes_data = getattr(WEIGHT_CODE_BUILDER_INST, CODES_CHANNEL_NAME) + data = CodeBuilderOutput.from_int(codes_data.value) + + symbol_valid_array = fields_as_array(data, "symbol_valid", 8) + code_length_array = fields_as_array(data, "code_length", 8) + code_array = fields_as_array(data, "code", 8) + + for symbol_valid, code_length, code in zip( + symbol_valid_array, code_length_array, code_array + ): + if symbol_valid == 1: + codes += [{"symbol": symbol_cnt, "code": code, "length": code_length}] + symbol_cnt += 1 + packet_cnt += 1 + + if packet_cnt == 32: + assert codes == reverse_expected_huffman_codes(expected_codes[block_cnt]) + packet_cnt = 0 + symbol_cnt = 0 + block_cnt += 1 + codes = [] + + cocotb.start_soon( + set_handshake_event(dut.clk, codes_channel, huffman_code_handshake) + ) + cocotb.start_soon(get_handshake_event(dut, huffman_code_handshake, func)) + + async def test_huffman_weights(dut, clock, expected_huffman_weights): lookup_dec_resp_channel = xlschannel.XLSChannel( dut.ZstdDecoder.xls_modules_zstd_huffman_ctrl__ZstdDecoderInst__ZstdDecoder_0__CompressBlockDecoder_0__LiteralsDecoder_0__HuffmanLiteralsDecoder_0__HuffmanControlAndSequence_0__32_64_next_inst20, @@ -498,6 +607,7 @@ async def testing_routine( expected_fse_lookups=None, expected_fse_huffman_lookups=None, expected_huffman_weights=None, + expected_huffman_codes=None, ): (axi_buses, cpu, clock) = prepare_test_environment(dut) frame_id = 0 @@ -508,6 +618,8 @@ async def testing_routine( await test_fse_lookup_decoder_for_huffman( dut, clock, expected_fse_huffman_lookups ) + if expected_huffman_codes is not None: + await test_huffman_codes(dut, clock, expected_huffman_codes) if expected_huffman_weights is not None: await test_huffman_weights(dut, clock, expected_huffman_weights) await test_decoder( @@ -661,6 +773,31 @@ async def pregenerated_compressed_random_1(dut): ], ] + expected_huffman_codes = [ + [ + {"code": 0x00, "length": 8, "symbol": 0x31}, + {"code": 0x01, "length": 8, "symbol": 0x35}, + {"code": 0x20, "length": 3, "symbol": 0x39}, + {"code": 0x02, "length": 8, "symbol": 0x6E}, + {"code": 0x03, "length": 8, "symbol": 0x72}, + {"code": 0x08, "length": 6, "symbol": 0x76}, + {"code": 0x40, "length": 2, "symbol": 0x7A}, + {"code": 0x04, "length": 8, "symbol": 0xAF}, + {"code": 0x05, "length": 8, "symbol": 0xB3}, + {"code": 0x0C, "length": 6, "symbol": 0xB7}, + {"code": 0x80, "length": 1, "symbol": 0xBB}, + {"code": 0x06, "length": 8, "symbol": 0xF0}, + {"code": 0x07, "length": 8, "symbol": 0xF4}, + {"code": 0x10, "length": 4, "symbol": 0xF8}, + ], + [ + {"code": 0x02, "length": 2, "symbol": 0x01}, + {"code": 0x00, "length": 3, "symbol": 0x66}, + {"code": 0x04, "length": 1, "symbol": 0x9C}, + {"code": 0x01, "length": 3, "symbol": 0xCB}, + ], + ] + expected_fse_huffman_lookups = [ [ FseTableRecord(symbol=0x00, num_of_bits=0x01, base=0x0016), @@ -804,6 +941,7 @@ async def pregenerated_compressed_random_1(dut): block_type, literal_type, input_name, + expected_huffman_codes=expected_huffman_codes, expected_huffman_weights=expected_huffman_weights, expected_fse_huffman_lookups=expected_fse_huffman_lookups, ) @@ -961,7 +1099,51 @@ async def fse_huffman_literals_predefined_sequences_seed_319146(dut): test_cases = 1 block_type = data_generator.BlockType.COMPRESSED literal_type = data_generator.LiteralType.RANDOM - await testing_routine(dut, test_cases, block_type, literal_type, input_name) + + expected_huffman_codes = [ + [ + {"code": 0x300, "length": 2, "symbol": 0x07}, + {"code": 0x60, "length": 5, "symbol": 0x0E}, + {"code": 0x0A, "length": 9, "symbol": 0x15}, + {"code": 0x00, "length": 10, "symbol": 0x1C}, + {"code": 0x180, "length": 3, "symbol": 0x25}, + {"code": 0x30, "length": 6, "symbol": 0x2C}, + {"code": 0x0C, "length": 9, "symbol": 0x33}, + {"code": 0x01, "length": 10, "symbol": 0x3A}, + {"code": 0xC0, "length": 4, "symbol": 0x43}, + {"code": 0x18, "length": 7, "symbol": 0x4A}, + {"code": 0x02, "length": 10, "symbol": 0x51}, + {"code": 0x100, "length": 4, "symbol": 0x61}, + {"code": 0x20, "length": 7, "symbol": 0x68}, + {"code": 0x03, "length": 10, "symbol": 0x6F}, + {"code": 0x80, "length": 5, "symbol": 0x7F}, + {"code": 0x10, "length": 8, "symbol": 0x86}, + {"code": 0x04, "length": 10, "symbol": 0x8D}, + {"code": 0x200, "length": 3, "symbol": 0x96}, + {"code": 0x40, "length": 6, "symbol": 0x9D}, + {"code": 0x0E, "length": 9, "symbol": 0xA4}, + {"code": 0x05, "length": 10, "symbol": 0xAB}, + {"code": 0x280, "length": 3, "symbol": 0xB4}, + {"code": 0x50, "length": 6, "symbol": 0xBB}, + {"code": 0x06, "length": 10, "symbol": 0xC2}, + {"code": 0x07, "length": 10, "symbol": 0xC9}, + {"code": 0x140, "length": 4, "symbol": 0xD2}, + {"code": 0x28, "length": 7, "symbol": 0xD9}, + {"code": 0x08, "length": 10, "symbol": 0xE0}, + {"code": 0xA0, "length": 5, "symbol": 0xF0}, + {"code": 0x14, "length": 8, "symbol": 0xF7}, + {"code": 0x09, "length": 10, "symbol": 0xFE}, + ] + ] + + await testing_routine( + dut, + test_cases, + block_type, + literal_type, + input_name, + expected_huffman_codes=expected_huffman_codes, + ) @cocotb.test(timeout_time=1000, timeout_unit="ms") @@ -973,7 +1155,38 @@ async def fse_huffman_literals_predefined_sequences_seed_331938(dut): test_cases = 1 block_type = data_generator.BlockType.COMPRESSED literal_type = data_generator.LiteralType.RANDOM - await testing_routine(dut, test_cases, block_type, literal_type, input_name) + + expected_huffman_codes = [ + [ + {"code": 0x00, "length": 9, "symbol": 0x13}, + {"code": 0x20, "length": 5, "symbol": 0x1B}, + {"code": 0x01, "length": 9, "symbol": 0x32}, + {"code": 0x10, "length": 6, "symbol": 0x3A}, + {"code": 0x100, "length": 2, "symbol": 0x42}, + {"code": 0x02, "length": 9, "symbol": 0x51}, + {"code": 0x18, "length": 6, "symbol": 0x59}, + {"code": 0x180, "length": 2, "symbol": 0x61}, + {"code": 0x08, "length": 7, "symbol": 0x78}, + {"code": 0x80, "length": 3, "symbol": 0x80}, + {"code": 0x0C, "length": 7, "symbol": 0x97}, + {"code": 0xC0, "length": 3, "symbol": 0x9F}, + {"code": 0x04, "length": 8, "symbol": 0xB6}, + {"code": 0x40, "length": 4, "symbol": 0xBE}, + {"code": 0x06, "length": 8, "symbol": 0xD5}, + {"code": 0x60, "length": 4, "symbol": 0xDD}, + {"code": 0x03, "length": 9, "symbol": 0xF4}, + {"code": 0x30, "length": 5, "symbol": 0xFC}, + ] + ] + + await testing_routine( + dut, + test_cases, + block_type, + literal_type, + input_name, + expected_huffman_codes=expected_huffman_codes, + ) @cocotb.test(timeout_time=350, timeout_unit="ms") @@ -1473,6 +1686,16 @@ async def treeless_huffman_literals_compressed_sequences_seed_400077(dut): ] ] + expected_huffman_codes = [ + [ + {"code": 0x00, "length": 4, "symbol": 0x00}, + {"code": 0x02, "length": 3, "symbol": 0x3D}, + {"code": 0x04, "length": 2, "symbol": 0x7A}, + {"code": 0x08, "length": 1, "symbol": 0xB7}, + {"code": 0x01, "length": 4, "symbol": 0xC3}, + ] + ] + expected_fse_huffman_lookups = [ [ FseTableRecord(symbol=0x00, num_of_bits=0x01, base=0x0018), @@ -1516,6 +1739,7 @@ async def treeless_huffman_literals_compressed_sequences_seed_400077(dut): block_type, literal_type, input_name, + expected_huffman_codes=expected_huffman_codes, expected_huffman_weights=expected_huffman_weights, expected_fse_huffman_lookups=expected_fse_huffman_lookups, ) @@ -1540,12 +1764,34 @@ async def treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400 ] ] + expected_huffman_codes = [ + [ + {"code": 0x00, "length": 4, "symbol": 0x00}, + {"code": 0x01, "length": 4, "symbol": 0x01}, + {"code": 0x02, "length": 4, "symbol": 0x02}, + {"code": 0x03, "length": 4, "symbol": 0x03}, + {"code": 0x04, "length": 4, "symbol": 0x04}, + {"code": 0x05, "length": 4, "symbol": 0x05}, + {"code": 0x06, "length": 4, "symbol": 0x06}, + {"code": 0x07, "length": 4, "symbol": 0x07}, + {"code": 0x08, "length": 4, "symbol": 0x08}, + {"code": 0x09, "length": 4, "symbol": 0x09}, + {"code": 0x0A, "length": 4, "symbol": 0x0A}, + {"code": 0x0B, "length": 4, "symbol": 0x0B}, + {"code": 0x0C, "length": 4, "symbol": 0x0C}, + {"code": 0x0D, "length": 4, "symbol": 0x0D}, + {"code": 0x0E, "length": 4, "symbol": 0x0E}, + {"code": 0x0F, "length": 4, "symbol": 0x0F}, + ] + ] + await testing_routine( dut, test_cases, block_type, literal_type, input_name, + expected_huffman_codes=expected_huffman_codes, expected_huffman_weights=expected_huffman_weights, ) @@ -1569,12 +1815,34 @@ async def treeless_huffman_literals_predefined_rle_compressed_sequences_seed_400 ] ] + expected_huffman_codes = [ + [ + {"code": 0x00, "length": 4, "symbol": 0x00}, + {"code": 0x01, "length": 4, "symbol": 0x01}, + {"code": 0x02, "length": 4, "symbol": 0x02}, + {"code": 0x03, "length": 4, "symbol": 0x03}, + {"code": 0x04, "length": 4, "symbol": 0x04}, + {"code": 0x05, "length": 4, "symbol": 0x05}, + {"code": 0x06, "length": 4, "symbol": 0x06}, + {"code": 0x07, "length": 4, "symbol": 0x07}, + {"code": 0x08, "length": 4, "symbol": 0x08}, + {"code": 0x09, "length": 4, "symbol": 0x09}, + {"code": 0x0A, "length": 4, "symbol": 0x0A}, + {"code": 0x0B, "length": 4, "symbol": 0x0B}, + {"code": 0x0C, "length": 4, "symbol": 0x0C}, + {"code": 0x0D, "length": 4, "symbol": 0x0D}, + {"code": 0x0E, "length": 4, "symbol": 0x0E}, + {"code": 0x0F, "length": 4, "symbol": 0x0F}, + ] + ] + await testing_routine( dut, test_cases, block_type, literal_type, input_name, + expected_huffman_codes=expected_huffman_codes, expected_huffman_weights=expected_huffman_weights, ) @@ -1623,6 +1891,26 @@ async def treeless_huffman_literals_rle_sequences_seed_403927(dut): ] ] + expected_huffman_codes = [ + [ + {"code": 0x0C, "length": 6, "symbol": 0x04}, + {"code": 0x00, "length": 8, "symbol": 0x07}, + {"code": 0x08, "length": 7, "symbol": 0x29}, + {"code": 0x01, "length": 8, "symbol": 0x2C}, + {"code": 0x0A, "length": 7, "symbol": 0x4E}, + {"code": 0x02, "length": 8, "symbol": 0x51}, + {"code": 0x80, "length": 1, "symbol": 0x70}, + {"code": 0x03, "length": 8, "symbol": 0x73}, + {"code": 0x04, "length": 8, "symbol": 0x76}, + {"code": 0x40, "length": 2, "symbol": 0x95}, + {"code": 0x05, "length": 8, "symbol": 0x98}, + {"code": 0x20, "length": 3, "symbol": 0xBA}, + {"code": 0x06, "length": 8, "symbol": 0xBD}, + {"code": 0x10, "length": 4, "symbol": 0xDF}, + {"code": 0x07, "length": 8, "symbol": 0xE2}, + ] + ] + expected_fse_huffman_lookups = [ [ FseTableRecord(symbol=0x00, num_of_bits=0x01, base=0x0012), @@ -1666,6 +1954,7 @@ async def treeless_huffman_literals_rle_sequences_seed_403927(dut): block_type, literal_type, input_name, + expected_huffman_codes=expected_huffman_codes, expected_huffman_weights=expected_huffman_weights, expected_fse_huffman_lookups=expected_fse_huffman_lookups, ) From 36ea2c313e7986c07919d299c88a65301627ec46 Mon Sep 17 00:00:00 2001 From: Dominik Lau Date: Tue, 29 Jul 2025 09:25:46 +0200 Subject: [PATCH 28/30] modules: zstd: cocotb: drop unused testcase --- xls/modules/zstd/zstd_dec_cocotb_test.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/xls/modules/zstd/zstd_dec_cocotb_test.py b/xls/modules/zstd/zstd_dec_cocotb_test.py index f685ce4fc4..c9c96d9544 100644 --- a/xls/modules/zstd/zstd_dec_cocotb_test.py +++ b/xls/modules/zstd/zstd_dec_cocotb_test.py @@ -1970,13 +1970,6 @@ async def zstd_compressed_frames_test(dut): literal_type = data_generator.LiteralType.RAW await testing_routine(dut, test_cases, block_type, literal_type) - -# @cocotb.test(timeout_time=1000, timeout_unit="ms") -# async def zstd_random_frames_test(dut): -# test_cases = 1 -# block_type = BlockType.RANDOM -# await testing_routine(dut, test_cases, block_type) - if __name__ == "__main__": sys.path.append(str(pathlib.Path(__file__).parent)) with tempfile.NamedTemporaryFile(mode="w") as modified_zstd_verilog: From 6f4ad2588c5130ca8f5570d04ae0067ce5b02a76 Mon Sep 17 00:00:00 2001 From: Dominik Lau Date: Thu, 21 Aug 2025 08:16:37 +0200 Subject: [PATCH 29/30] modules: zstd: disable huffman code builder PnR --- xls/modules/zstd/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xls/modules/zstd/BUILD b/xls/modules/zstd/BUILD index 620d743f98..1a05177799 100644 --- a/xls/modules/zstd/BUILD +++ b/xls/modules/zstd/BUILD @@ -3353,7 +3353,7 @@ benchmark_synth( ) place_and_route( - name = "huffman_code_builder_place_and_route", + name = "huffman_code_builder_place_and_route_skip", clock_period = CLOCK_PERIOD_PS, core_padding_microns = 2, min_pin_distance = "0.5", From be9a0668ec29b90261468245a467728df1f1673e Mon Sep 17 00:00:00 2001 From: Dominik Lau Date: Thu, 21 Aug 2025 08:26:56 +0200 Subject: [PATCH 30/30] modules: zstd: fix formatting --- xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.log | 1 - xls/modules/zstd/zstd_dec_ll_fse_default.mem | 2 +- xls/modules/zstd/zstd_dec_ml_fse_default.mem | 2 +- xls/modules/zstd/zstd_dec_of_fse_default.mem | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.log b/xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.log index ea44ca6642..bf6b092bbe 100644 --- a/xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.log +++ b/xls/modules/zstd/data/rle_literals_rle_sequences_seed_2.log @@ -40,4 +40,3 @@ frame seed: 2 number of sequences: 1 block type: compressed block size field: 10 - diff --git a/xls/modules/zstd/zstd_dec_ll_fse_default.mem b/xls/modules/zstd/zstd_dec_ll_fse_default.mem index f61d7ce353..fd3bfafa24 100644 --- a/xls/modules/zstd/zstd_dec_ll_fse_default.mem +++ b/xls/modules/zstd/zstd_dec_ll_fse_default.mem @@ -253,4 +253,4 @@ 00000000 00000000 00000000 -00000000 \ No newline at end of file +00000000 diff --git a/xls/modules/zstd/zstd_dec_ml_fse_default.mem b/xls/modules/zstd/zstd_dec_ml_fse_default.mem index 704d69a731..04b32295c8 100644 --- a/xls/modules/zstd/zstd_dec_ml_fse_default.mem +++ b/xls/modules/zstd/zstd_dec_ml_fse_default.mem @@ -253,4 +253,4 @@ 00000000 00000000 00000000 -00000000 \ No newline at end of file +00000000 diff --git a/xls/modules/zstd/zstd_dec_of_fse_default.mem b/xls/modules/zstd/zstd_dec_of_fse_default.mem index 2872c3e282..9d81689c66 100644 --- a/xls/modules/zstd/zstd_dec_of_fse_default.mem +++ b/xls/modules/zstd/zstd_dec_of_fse_default.mem @@ -253,4 +253,4 @@ 00000000 00000000 00000000 -00000000 \ No newline at end of file +00000000