Created
August 5, 2026 12:22
-
-
Save soronpo/ed02da10b82ed44ee8a21f04cfc0a4ed to your computer and use it in GitHub Desktop.
DFHDL #449 minimized - 8 files, 262 lines
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| // unreferenced by anything; present in the compilation unit only | |
| class abs(val DATA_WIDTH: Int <> CONST = 8) extends EDDesign: | |
| val i = Bits(DATA_WIDTH) <> IN | |
| val o = Bits(DATA_WIDTH) <> OUT | |
| o <> i |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class binning( | |
| val DATA_WIDTH: Int <> CONST = 8, | |
| val IMAGE_WIDTH: Int <> CONST = 640, | |
| val IMAGE_HEIGHT: Int <> CONST = 480 | |
| ) extends EDDesign: | |
| val clk, rst = Bit <> IN | |
| val pixel_valid = Bit <> IN | |
| val bin_ready = Bit <> IN | |
| val pixel = Bits(DATA_WIDTH) <> IN | |
| val bin_valid = Bit <> OUT | |
| val pixel_ready = Bit <> OUT | |
| val magnitude = UInt(DATA_WIDTH) <> OUT | |
| val bin = UInt(4) <> OUT | |
| bin_valid <> 0 | |
| magnitude <> 0 | |
| bin <> 0 | |
| // the only thing that matters here: lin_buff at a 4th parameter set | |
| val image_line_buff = new lin_buff( | |
| BUFFER_WIDTH = DATA_WIDTH, BUFFER_DEPTH = IMAGE_WIDTH, | |
| BLOCK_WIDTH = 3, BLOCK_HEIGHT = 3) | |
| image_line_buff.clk <> clk | |
| image_line_buff.rst <> rst | |
| image_line_buff.p_valid <> pixel_valid | |
| image_line_buff.pixel <> pixel | |
| image_line_buff.k_ready <> bin_ready | |
| pixel_ready <> image_line_buff.p_ready | |
| image_line_buff.k_border <> OPEN | |
| image_line_buff.k_valid <> OPEN | |
| image_line_buff.kernel <> OPEN |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class cell_histogram( | |
| val DATA_WIDTH: Int <> CONST = 8, | |
| val IMAGE_WIDTH: Int <> CONST = 640, | |
| val INPUT_BIN_WIDTH: Int <> CONST = 11, | |
| val OUTPUT_BIN_WIDTH: Int <> CONST = 14 | |
| ) extends EDDesign: | |
| val HISTOGRAM_WIDTH: Int <> CONST = OUTPUT_BIN_WIDTH * 10 | |
| val BINS: Int <> CONST = 9 + 1 | |
| val PARTIAL_HISTOGRAM_WIDTH: Int <> CONST = INPUT_BIN_WIDTH * BINS | |
| val CELL_PARTIAL_HISTOGRAM_WIDTH: Int <> CONST = PARTIAL_HISTOGRAM_WIDTH * 8 | |
| // IMAGE_WIDTH (the edited parameter) reaches lin_buff through here | |
| val CELLS_PER_ROW: Int <> CONST = IMAGE_WIDTH / 8 | |
| val clk, rst = Bit <> IN | |
| val in_valid = Bit <> IN | |
| val out_ready = Bit <> IN | |
| val magnitude = UInt(DATA_WIDTH) <> IN | |
| val bin_index = UInt(4) <> IN | |
| val out_valid = Bit <> OUT | |
| val in_ready = Bit <> OUT | |
| val full_histogram = Bits(HISTOGRAM_WIDTH) <> OUT | |
| out_valid <> 0 | |
| in_ready <> 0 | |
| val cell_buff = new lin_buff( | |
| BUFFER_WIDTH = PARTIAL_HISTOGRAM_WIDTH, BUFFER_DEPTH = CELLS_PER_ROW, | |
| BLOCK_WIDTH = 1, BLOCK_HEIGHT = 8) | |
| cell_buff.clk <> clk; cell_buff.rst <> rst | |
| cell_buff.p_valid <> in_valid; cell_buff.pixel <> all(0); cell_buff.k_ready <> out_ready | |
| cell_buff.p_ready <> OPEN; cell_buff.k_border <> OPEN; cell_buff.k_valid <> OPEN | |
| cell_buff.kernel <> OPEN | |
| val histogram_adder = new partial_histogram_add( | |
| INPUT_BIN_WIDTH = INPUT_BIN_WIDTH, OUTPUT_BIN_WIDTH = OUTPUT_BIN_WIDTH, BINS = BINS) | |
| histogram_adder.partial_histogram <> all(0) | |
| full_histogram <> histogram_adder.full_histogram |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class detection_window( | |
| val IMAGE_WIDTH: Int <> CONST = 640, | |
| val INPUT_WIDTH: Int <> CONST = 36, | |
| val BLOCKS_PER_WINDOW: Int <> CONST = 32 | |
| ) extends EDDesign: | |
| val OUTPUT_WIDTH = INPUT_WIDTH * BLOCKS_PER_WINDOW | |
| val clk, rst = Bit <> IN | |
| val in_valid = Bit <> IN | |
| val out_ready = Bit <> IN | |
| val normalized_block = Bits(INPUT_WIDTH) <> IN | |
| val out_valid = Bit <> OUT | |
| val in_ready = Bit <> OUT | |
| val detection_window = Bits(OUTPUT_WIDTH) <> OUT | |
| val IMAGE_ROW_BLOCKS: Int <> CONST = IMAGE_WIDTH / 16 | |
| val WINDOW_ROW_BLOCKS: Int <> CONST = 64 / 16 | |
| val WINDOW_COLUMN_BLOCKS: Int <> CONST = 128 / 16 | |
| out_valid <> 0 | |
| val block_line_buffer = new lin_buff( | |
| BUFFER_WIDTH = INPUT_WIDTH, BUFFER_DEPTH = IMAGE_ROW_BLOCKS, | |
| BLOCK_WIDTH = WINDOW_ROW_BLOCKS, BLOCK_HEIGHT = WINDOW_COLUMN_BLOCKS) | |
| block_line_buffer.clk <> clk | |
| block_line_buffer.rst <> rst | |
| block_line_buffer.p_valid <> in_valid | |
| block_line_buffer.pixel <> normalized_block | |
| block_line_buffer.k_ready <> out_ready | |
| in_ready <> block_line_buffer.p_ready | |
| block_line_buffer.k_border <> OPEN | |
| block_line_buffer.k_valid <> OPEN | |
| detection_window <> block_line_buffer.kernel.resize(OUTPUT_WIDTH) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class hog( | |
| val DATA_WIDTH: Int <> CONST = 8, | |
| val IMAGE_WIDTH: Int <> CONST = 640, | |
| val IMAGE_HEIGHT: Int <> CONST = 480, | |
| val WINDOW_WIDTH: Int <> CONST = 32 * 36 | |
| ) extends EDDesign: | |
| val clk, rst = Bit <> IN | |
| val pixel_valid = Bit <> IN | |
| val window_ready = Bit <> IN | |
| val pixel = Bits(DATA_WIDTH) <> IN | |
| val window_valid = Bit <> OUT | |
| val pixel_ready = Bit <> OUT | |
| val detection_window = Bits(WINDOW_WIDTH) <> OUT | |
| val HISTOGRAM_WIDTH: Int <> CONST = 10 * 14 // BINS * BIN_WIDTH | |
| val NORM_BLOCK_WIDTH: Int <> CONST = 36 | |
| val magnitude = UInt(DATA_WIDTH) <> VAR | |
| val bin = UInt(4) <> VAR | |
| val cell_histogram = Bits(HISTOGRAM_WIDTH) <> VAR | |
| val normalized_block = Bits(NORM_BLOCK_WIDTH) <> VAR | |
| val bin_ready, bin_valid = Bit <> VAR | |
| val cell_valid, cell_ready = Bit <> VAR | |
| val block_valid, block_ready = Bit <> VAR | |
| val u_binning = new binning( | |
| DATA_WIDTH = DATA_WIDTH, | |
| IMAGE_WIDTH = IMAGE_WIDTH, | |
| IMAGE_HEIGHT = IMAGE_HEIGHT | |
| ) | |
| u_binning.clk <> clk | |
| u_binning.rst <> rst | |
| u_binning.pixel_valid <> pixel_valid | |
| u_binning.bin_ready <> bin_ready | |
| u_binning.pixel <> pixel | |
| bin_valid <> u_binning.bin_valid | |
| pixel_ready <> u_binning.pixel_ready | |
| magnitude <> u_binning.magnitude | |
| bin <> u_binning.bin | |
| val u_cell_histogram = new cell_histogram( | |
| DATA_WIDTH = DATA_WIDTH, | |
| IMAGE_WIDTH = IMAGE_WIDTH, | |
| INPUT_BIN_WIDTH = 11, | |
| OUTPUT_BIN_WIDTH = 14 | |
| ) | |
| u_cell_histogram.clk <> clk | |
| u_cell_histogram.rst <> rst | |
| u_cell_histogram.in_valid <> bin_valid | |
| u_cell_histogram.out_ready <> cell_ready | |
| u_cell_histogram.magnitude <> magnitude | |
| u_cell_histogram.bin_index <> bin | |
| cell_valid <> u_cell_histogram.out_valid | |
| bin_ready <> u_cell_histogram.in_ready | |
| cell_histogram <> u_cell_histogram.full_histogram | |
| // the remaining parameters are left at their defaults, as in the gold | |
| val u_norm_block = new norm_block( | |
| IMAGE_WIDTH = IMAGE_WIDTH, | |
| IMAGE_HEIGHT = IMAGE_HEIGHT | |
| ) | |
| u_norm_block.clk <> clk | |
| u_norm_block.rst <> rst | |
| u_norm_block.in_valid <> cell_valid | |
| u_norm_block.out_ready <> block_ready | |
| u_norm_block.cell_histogram <> cell_histogram | |
| block_valid <> u_norm_block.out_valid | |
| cell_ready <> u_norm_block.in_ready | |
| normalized_block <> u_norm_block.normalized_block | |
| val u_detection_window = new detection_window(IMAGE_WIDTH = IMAGE_WIDTH) | |
| u_detection_window.clk <> clk | |
| u_detection_window.rst <> rst | |
| u_detection_window.in_valid <> block_valid | |
| u_detection_window.out_ready <> window_ready | |
| u_detection_window.normalized_block <> normalized_block | |
| window_valid <> u_detection_window.out_valid | |
| block_ready <> u_detection_window.in_ready | |
| // WINDOW_WIDTH is its own parameter here (32 * 36) while the child derives | |
| // INPUT_WIDTH * BLOCKS_PER_WINDOW; both are 1152 but nothing ties them. | |
| detection_window <> u_detection_window.detection_window.resize(WINDOW_WIDTH) | |
| end hog |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class lin_buff( | |
| val BUFFER_WIDTH: Int <> CONST = 8, | |
| val BUFFER_DEPTH: Int <> CONST = 854, | |
| val BLOCK_WIDTH: Int <> CONST = 3, | |
| val BLOCK_HEIGHT: Int <> CONST = 3 | |
| ) extends EDDesign: | |
| val OUTPUT_WIDTH = BLOCK_WIDTH * BLOCK_HEIGHT * BUFFER_WIDTH | |
| val MID_ROWS = BLOCK_HEIGHT - 2 | |
| val clk, rst = Bit <> IN | |
| val p_valid = Bit <> IN | |
| val pixel = Bits(BUFFER_WIDTH) <> IN | |
| val k_ready = Bit <> IN | |
| val p_ready = Bit <> OUT | |
| val k_border = Bit <> OUT | |
| val k_valid = Bit <> OUT | |
| val kernel = Bits(OUTPUT_WIDTH) <> OUT | |
| p_ready <> 0 | |
| k_border <> 0 | |
| k_valid <> 0 | |
| kernel <> all(0) | |
| // structure-bearing loop retained; the child design is gone | |
| for (i <- 0 until MID_ROWS) | |
| val w = Bits(BUFFER_WIDTH) <> VAR | |
| w <> pixel |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class norm_block( | |
| val IMAGE_WIDTH: Int <> CONST = 640, | |
| val IMAGE_HEIGHT: Int <> CONST = 480, | |
| val BLOCK_ROW_CELLS: Int <> CONST = 2, | |
| val BLOCK_COLUMN_CELLS: Int <> CONST = 2, | |
| val BIN_WIDTH: Int <> CONST = 14, | |
| val BINS: Int <> CONST = 9, | |
| val CELLS_PER_BLOCK: Int <> CONST = 4 | |
| ) extends EDDesign: | |
| val HISTOGRAM_WIDTH: Int <> CONST = BIN_WIDTH * (BINS + 1) | |
| val OUTPUT_WIDTH: Int <> CONST = BINS * CELLS_PER_BLOCK | |
| val CELLS_PER_LINE: Int <> CONST = IMAGE_WIDTH / 8 | |
| val clk, rst = Bit <> IN | |
| val in_valid = Bit <> IN | |
| val out_ready = Bit <> IN | |
| val cell_histogram = Bits(HISTOGRAM_WIDTH) <> IN | |
| val out_valid = Bit <> OUT | |
| val in_ready = Bit <> OUT | |
| val normalized_block = Bits(OUTPUT_WIDTH) <> OUT | |
| out_valid <> 0 | |
| normalized_block <> all(0) | |
| val cell_line_buffer = new lin_buff( | |
| BUFFER_WIDTH = HISTOGRAM_WIDTH, BUFFER_DEPTH = CELLS_PER_LINE, | |
| BLOCK_WIDTH = BLOCK_ROW_CELLS, BLOCK_HEIGHT = BLOCK_COLUMN_CELLS) | |
| cell_line_buffer.clk <> clk | |
| cell_line_buffer.rst <> rst | |
| cell_line_buffer.p_valid <> in_valid | |
| cell_line_buffer.pixel <> cell_histogram | |
| cell_line_buffer.k_ready <> out_ready | |
| in_ready <> cell_line_buffer.p_ready | |
| cell_line_buffer.k_border <> OPEN | |
| cell_line_buffer.k_valid <> OPEN | |
| cell_line_buffer.kernel <> OPEN |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import dfhdl.* | |
| class partial_histogram_add( | |
| val INPUT_BIN_WIDTH: Int <> CONST = 11, | |
| val OUTPUT_BIN_WIDTH: Int <> CONST = 14, | |
| val BINS: Int <> CONST = 9, // number of bins in each histogram | |
| val CELL_ROWS: Int <> CONST = 8 // number of rows per cell, number of partial histograms | |
| ) extends EDDesign: | |
| val INPUT_WIDTH = INPUT_BIN_WIDTH * BINS * CELL_ROWS | |
| val OUTPUT_WIDTH = OUTPUT_BIN_WIDTH * BINS | |
| /** 8 partial histograms as 1 vector */ | |
| val partial_histogram = Bits(INPUT_WIDTH) <> IN | |
| /** one full histogram output */ | |
| val full_histogram = Bits(OUTPUT_WIDTH) <> OUT | |
| // The gold hardcodes the per-row byte offsets (99 == INPUT_BIN_WIDTH * BINS) | |
| // rather than deriving them, so they are kept literal here too. | |
| val ROW_OFFSETS = List(0, 99, 198, 297, 396, 495, 594, 693) | |
| // Multi-bit slices of an output port are not connectable more than once | |
| // (`<>` reports "multiple connections write to the same port"), so the | |
| // per-bin writes are assignments inside a process instead. | |
| process(all): | |
| for (i <- 0 until BINS) | |
| // the ith bin of the output is the sum of | |
| // the ith bins of each row (partial histogram) | |
| // Verilog evaluates the 8-term sum at the 14-bit target width, so each | |
| // 11-bit addend is zero-extended first. | |
| full_histogram.lsbitsAt(i * OUTPUT_BIN_WIDTH, OUTPUT_BIN_WIDTH) := | |
| ROW_OFFSETS | |
| .map(off => | |
| partial_histogram | |
| .lsbitsAt(i * INPUT_BIN_WIDTH + off, INPUT_BIN_WIDTH) | |
| .resize(OUTPUT_BIN_WIDTH) | |
| ) | |
| .reduce(_ + _) | |
| end partial_histogram_add |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # DFHDL #449 minimized repro. MUST run in a directory that has never been | |
| # compiled before -- copy this tree to a NEW path for each attempt (bloop's | |
| # incremental state, keyed by project path, suppresses the crash on re-runs). | |
| set -u | |
| V=$(cat ~/.dfhdl_version) | |
| b(){ scala run src/ --scala 3.8.4 --dep "io.github.dfianthdl::dfhdl::$V" \ | |
| --compiler-plugin "io.github.dfianthdl:::dfhdl-plugin::$V" -O -deprecation -M "$1" -- commit 2>&1; } | |
| echo "1. prime with hog"; b hog >/tmp/1.log 2>&1 && echo " ok" || { tail -3 /tmp/1.log; exit 1; } | |
| echo "2. build cell_histogram"; b cell_histogram >/tmp/2.log 2>&1 && echo " ok" || { tail -3 /tmp/2.log; exit 1; } | |
| echo "3. change one parameter default" | |
| sed -i 's/IMAGE_WIDTH: Int <> CONST = 640/IMAGE_WIDTH: Int <> CONST = 64/' src/cell_histogram.scala | |
| echo "4. rebuild cell_histogram" | |
| b cell_histogram >/tmp/3.log 2>&1 && echo " ok (did NOT reproduce - was this path used before?)" \ | |
| || { grep -m1 NoSuchElementException /tmp/3.log; echo " REPRODUCED"; } | |
| echo "5. clear dfhdl-cache, rebuild identical source" | |
| find src/.scala-build -name dfhdl-cache -type d -exec rm -rf {} + 2>/dev/null | |
| b cell_histogram >/tmp/4.log 2>&1 && echo " ok - same source elaborates fine once the cache is gone" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment