import "core.futil"; // An implementation of Comparator Network Longest Prefix Match (CN-LPM), as described in: // "TCAM-based high speed longest prefix matching with fast incremental table updates" // Rasmussen et al. (2013) [https://ieeexplore.ieee.org/document/6602288] // // A lengthier write-up on the design can be found at: // https://cgyurgyik.github.io/posts/2021/05/tcam-in-calyx/ // Sets the `out` signal to high if the value `in` matches the // `prefix` with the given `length`. For example, given // in = 5'b11000, prefix = 5'b11001, length = 2: // our prefix-match may be represented as `11xxx`, where `x` // is a "don't care" bit. Since `in` does indeed match the // prefix `11xxx`, the `match_line` signal is set to high. // // Note: the length is an N-bit value, // which means length `0` really means length `1`, // and more generally, `N-1` length represents `N`. // The zero case is caught earlier so that // we only need N bits to represent length. component match_element(in: 32, prefix: 32, length: 5) -> (out: 1) { cells { sub = std_sub(5); pad = std_pad(5, 32); rsh0 = std_rsh(32); rsh1 = std_rsh(32); eq = std_eq(32); r = std_reg(1); } wires { group compare<"static"=1> { sub.left = 5'd31; sub.right = length; pad.in = sub.out; rsh0.left = in; rsh0.right = pad.out; rsh1.left = prefix; rsh1.right = pad.out; eq.left = rsh0.out; eq.right = rsh1.out; r.write_en = 1'd1; r.in = eq.out; compare[done] = r.done; } out = r.out; } control { compare; } } // Given two addresses A and B with their lengths and match line, sets the `X` ports // with the address and length of the maximum length (valid) prefix match. The output // match line is set as the logical OR of the match lines from A and B. For example, // // lenA: 4, mlA: 1, addrA: 0 // lenB: 3, mlB: 1, addrB: 1 // Since lenA > lenB and the match line of A is high, // `lenX` = 4, `mlX` = 1, and `addrX` = 0. component comparator_element(lenA: 5, lenB: 5, addrA: 5, addrB: 5, mlA: 1, mlB: 1) -> (lenX: 5, addrX: 5, mlX: 1) { cells { gt0 = std_gt(5); or0 = std_or(1); or1 = std_or(1); not0 = std_not(1); and0 = std_and(1); len = std_reg(5); addr = std_reg(5); ml = std_reg(1); } wires { comb group select { gt0.left = lenA; gt0.right = lenB; not0.in = mlB; or0.left = not0.out; or0.right = gt0.out; and0.left = mlA; and0.right = or0.out; } group A<"static"=1> { len.write_en = 1'd1; addr.write_en = 1'd1; len.in = lenA; addr.in = addrA; A[done] = len.done & addr.done ? 1'd1; } group B<"static"=1> { len.write_en = 1'd1; addr.write_en = 1'd1; len.in = lenB; addr.in = addrB; B[done] = len.done & addr.done ? 1'd1; } group or_match_line<"static"=1> { or1.left = mlA; or1.right = mlB; ml.write_en = 1'd1; ml.in = or1.out; or_match_line[done] = ml.done; } mlX = ml.out; addrX = addr.out; lenX = len.out; } control { par { if and0.out with select { A; } else { B; } or_match_line; } } } // A ternary content-addressable memory (TCAM) for IPv4, implemented // using CN-LPM. One can either write to the TCAM or search the TCAM. // Each stage in the TCAM is separated by registers to allow // pipelining in the future. // // To write to the TCAM: // 1. Set the `write_en` signal high. // 2. Provide an `in` value and a corresponding `prefix_len`. // For example, if you want to represent the prefix-match // `101xx`, you'd pass in `0b'00101` with prefix_len `3`. // // To search the TCAM: // 1. Set the `search_en` signal high. // 2. Provide an `in` value indicating the data you're searching. // 3. Once the `done` signal is high, the `index` signal will contain the result // till the next invocation. // // The `write_en` and `search_en` signals should NOT be set to high // in the same invocation. If a zero-length prefix is written to the TCAM, // then invalid searches will be set to the corresponding index. Otherwise, // invalid searches will be defaulted to index zero. component TCAM_IPv4(write_en: 1, search_en: 1, in: 32, prefix_len: 6, write_index: 5) -> (index: 5) { cells { write_en_reg = std_reg(1); search_en_reg = std_reg(1); ce40_reg = std_reg(1); p0 = std_reg(32); p1 = std_reg(32); p2 = std_reg(32); p3 = std_reg(32); p4 = std_reg(32); p5 = std_reg(32); p6 = std_reg(32); p7 = std_reg(32); p8 = std_reg(32); p9 = std_reg(32); p10 = std_reg(32); p11 = std_reg(32); p12 = std_reg(32); p13 = std_reg(32); p14 = std_reg(32); p15 = std_reg(32); p16 = std_reg(32); p17 = std_reg(32); p18 = std_reg(32); p19 = std_reg(32); p20 = std_reg(32); p21 = std_reg(32); p22 = std_reg(32); p23 = std_reg(32); p24 = std_reg(32); p25 = std_reg(32); p26 = std_reg(32); p27 = std_reg(32); p28 = std_reg(32); p29 = std_reg(32); p30 = std_reg(32); p31 = std_reg(32); l0 = std_reg(5); l1 = std_reg(5); l2 = std_reg(5); l3 = std_reg(5); l4 = std_reg(5); l5 = std_reg(5); l6 = std_reg(5); l7 = std_reg(5); l8 = std_reg(5); l9 = std_reg(5); l10 = std_reg(5); l11 = std_reg(5); l12 = std_reg(5); l13 = std_reg(5); l14 = std_reg(5); l15 = std_reg(5); l16 = std_reg(5); l17 = std_reg(5); l18 = std_reg(5); l19 = std_reg(5); l20 = std_reg(5); l21 = std_reg(5); l22 = std_reg(5); l23 = std_reg(5); l24 = std_reg(5); l25 = std_reg(5); l26 = std_reg(5); l27 = std_reg(5); l28 = std_reg(5); l29 = std_reg(5); l30 = std_reg(5); l31 = std_reg(5); is_index0 = std_eq(5); is_index1 = std_eq(5); is_index2 = std_eq(5); is_index3 = std_eq(5); is_index4 = std_eq(5); is_index5 = std_eq(5); is_index6 = std_eq(5); is_index7 = std_eq(5); is_index8 = std_eq(5); is_index9 = std_eq(5); is_index10 = std_eq(5); is_index11 = std_eq(5); is_index12 = std_eq(5); is_index13 = std_eq(5); is_index14 = std_eq(5); is_index15 = std_eq(5); is_index16 = std_eq(5); is_index17 = std_eq(5); is_index18 = std_eq(5); is_index19 = std_eq(5); is_index20 = std_eq(5); is_index21 = std_eq(5); is_index22 = std_eq(5); is_index23 = std_eq(5); is_index24 = std_eq(5); is_index25 = std_eq(5); is_index26 = std_eq(5); is_index27 = std_eq(5); is_index28 = std_eq(5); is_index29 = std_eq(5); is_index30 = std_eq(5); is_index31 = std_eq(5); zero_index = std_reg(5); w_eq = std_eq(1); s_eq = std_eq(1); z_eq = std_eq(6); is_invalid = std_eq(1); slice = std_slice(6, 5); sub = std_sub(6); me0 = match_element(); me1 = match_element(); me2 = match_element(); me3 = match_element(); me4 = match_element(); me5 = match_element(); me6 = match_element(); me7 = match_element(); me8 = match_element(); me9 = match_element(); me10 = match_element(); me11 = match_element(); me12 = match_element(); me13 = match_element(); me14 = match_element(); me15 = match_element(); me16 = match_element(); me17 = match_element(); me18 = match_element(); me19 = match_element(); me20 = match_element(); me21 = match_element(); me22 = match_element(); me23 = match_element(); me24 = match_element(); me25 = match_element(); me26 = match_element(); me27 = match_element(); me28 = match_element(); me29 = match_element(); me30 = match_element(); me31 = match_element(); ce00 = comparator_element(); ce01 = comparator_element(); ce02 = comparator_element(); ce03 = comparator_element(); ce04 = comparator_element(); ce05 = comparator_element(); ce06 = comparator_element(); ce07 = comparator_element(); ce08 = comparator_element(); ce09 = comparator_element(); ce010 = comparator_element(); ce011 = comparator_element(); ce012 = comparator_element(); ce013 = comparator_element(); ce014 = comparator_element(); ce015 = comparator_element(); ce10 = comparator_element(); ce11 = comparator_element(); ce12 = comparator_element(); ce13 = comparator_element(); ce14 = comparator_element(); ce15 = comparator_element(); ce16 = comparator_element(); ce17 = comparator_element(); ce20 = comparator_element(); ce21 = comparator_element(); ce22 = comparator_element(); ce23 = comparator_element(); ce30 = comparator_element(); ce31 = comparator_element(); ce40 = comparator_element(); comb_reg0 = std_reg(1); comb_reg1 = std_reg(1); comb_reg2 = std_reg(1); comb_reg3 = std_reg(1); comb_reg4 = std_reg(1); comb_reg5 = std_reg(1); comb_reg6 = std_reg(1); comb_reg7 = std_reg(1); comb_reg8 = std_reg(1); comb_reg9 = std_reg(1); comb_reg10 = std_reg(1); comb_reg11 = std_reg(1); comb_reg12 = std_reg(1); comb_reg13 = std_reg(1); comb_reg14 = std_reg(1); comb_reg15 = std_reg(1); comb_reg16 = std_reg(1); comb_reg17 = std_reg(1); comb_reg18 = std_reg(1); comb_reg19 = std_reg(1); comb_reg20 = std_reg(1); comb_reg21 = std_reg(1); comb_reg22 = std_reg(1); comb_reg23 = std_reg(1); comb_reg24 = std_reg(1); comb_reg25 = std_reg(1); comb_reg26 = std_reg(1); comb_reg27 = std_reg(1); comb_reg28 = std_reg(1); comb_reg29 = std_reg(1); comb_reg30 = std_reg(1); comb_reg31 = std_reg(1); out = std_reg(5); } wires { group write_write_en_reg { write_en_reg.write_en = 1'd1; write_en_reg.in = write_en; write_write_en_reg[done] = write_en_reg.done; } group write_search_en_reg { search_en_reg.write_en = 1'd1; search_en_reg.in = search_en; write_search_en_reg[done] = search_en_reg.done; } group write_ce40_reg { ce40_reg.write_en = 1'd1; ce40_reg.in = ce40.mlX; write_ce40_reg[done] = ce40_reg.done; } comb group is_length_zero { z_eq.left = 6'd0; z_eq.right = prefix_len; } group write_zero<"static"=1> { zero_index.write_en = 1'd1; zero_index.in = write_index; write_zero[done] = zero_index.done; } group write0<"static"=1> { p0.write_en = write_en; l0.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l0.in = slice.out; p0.in = in; write0[done] = p0.done & l0.done ? 1'd1; } group write1<"static"=1> { p1.write_en = write_en; l1.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l1.in = slice.out; p1.in = in; write1[done] = p1.done & l1.done ? 1'd1; } group write2<"static"=1> { p2.write_en = write_en; l2.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l2.in = slice.out; p2.in = in; write2[done] = p2.done & l2.done ? 1'd1; } group write3<"static"=1> { p3.write_en = write_en; l3.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l3.in = slice.out; p3.in = in; write3[done] = p3.done & l3.done ? 1'd1; } group write4<"static"=1> { p4.write_en = write_en; l4.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l4.in = slice.out; p4.in = in; write4[done] = p4.done & l4.done ? 1'd1; } group write5<"static"=1> { p5.write_en = write_en; l5.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l5.in = slice.out; p5.in = in; write5[done] = p5.done & l5.done ? 1'd1; } group write6<"static"=1> { p6.write_en = write_en; l6.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l6.in = slice.out; p6.in = in; write6[done] = p6.done & l6.done ? 1'd1; } group write7<"static"=1> { p7.write_en = write_en; l7.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l7.in = slice.out; p7.in = in; write7[done] = p7.done & l7.done ? 1'd1; } group write8<"static"=1> { p8.write_en = write_en; l8.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l8.in = slice.out; p8.in = in; write8[done] = p8.done & l8.done ? 1'd1; } group write9<"static"=1> { p9.write_en = write_en; l9.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l9.in = slice.out; p9.in = in; write9[done] = p9.done & l9.done ? 1'd1; } group write10<"static"=1> { p10.write_en = write_en; l10.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l10.in = slice.out; p10.in = in; write10[done] = p10.done & l10.done ? 1'd1; } group write11<"static"=1> { p11.write_en = write_en; l11.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l11.in = slice.out; p11.in = in; write11[done] = p11.done & l11.done ? 1'd1; } group write12<"static"=1> { p12.write_en = write_en; l12.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l12.in = slice.out; p12.in = in; write12[done] = p12.done & l12.done ? 1'd1; } group write13<"static"=1> { p13.write_en = write_en; l13.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l13.in = slice.out; p13.in = in; write13[done] = p13.done & l13.done ? 1'd1; } group write14<"static"=1> { p14.write_en = write_en; l14.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l14.in = slice.out; p14.in = in; write14[done] = p14.done & l14.done ? 1'd1; } group write15<"static"=1> { p15.write_en = write_en; l15.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l15.in = slice.out; p15.in = in; write15[done] = p15.done & l15.done ? 1'd1; } group write16<"static"=1> { p16.write_en = write_en; l16.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l16.in = slice.out; p16.in = in; write16[done] = p16.done & l16.done ? 1'd1; } group write17<"static"=1> { p17.write_en = write_en; l17.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l17.in = slice.out; p17.in = in; write17[done] = p17.done & l17.done ? 1'd1; } group write18<"static"=1> { p18.write_en = write_en; l18.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l18.in = slice.out; p18.in = in; write18[done] = p18.done & l18.done ? 1'd1; } group write19<"static"=1> { p19.write_en = write_en; l19.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l19.in = slice.out; p19.in = in; write19[done] = p19.done & l19.done ? 1'd1; } group write20<"static"=1> { p20.write_en = write_en; l20.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l20.in = slice.out; p20.in = in; write20[done] = p20.done & l20.done ? 1'd1; } group write21<"static"=1> { p21.write_en = write_en; l21.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l21.in = slice.out; p21.in = in; write21[done] = p21.done & l21.done ? 1'd1; } group write22<"static"=1> { p22.write_en = write_en; l22.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l22.in = slice.out; p22.in = in; write22[done] = p22.done & l22.done ? 1'd1; } group write23<"static"=1> { p23.write_en = write_en; l23.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l23.in = slice.out; p23.in = in; write23[done] = p23.done & l23.done ? 1'd1; } group write24<"static"=1> { p24.write_en = write_en; l24.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l24.in = slice.out; p24.in = in; write24[done] = p24.done & l24.done ? 1'd1; } group write25<"static"=1> { p25.write_en = write_en; l25.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l25.in = slice.out; p25.in = in; write25[done] = p25.done & l25.done ? 1'd1; } group write26<"static"=1> { p26.write_en = write_en; l26.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l26.in = slice.out; p26.in = in; write26[done] = p26.done & l26.done ? 1'd1; } group write27<"static"=1> { p27.write_en = write_en; l27.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l27.in = slice.out; p27.in = in; write27[done] = p27.done & l27.done ? 1'd1; } group write28<"static"=1> { p28.write_en = write_en; l28.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l28.in = slice.out; p28.in = in; write28[done] = p28.done & l28.done ? 1'd1; } group write29<"static"=1> { p29.write_en = write_en; l29.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l29.in = slice.out; p29.in = in; write29[done] = p29.done & l29.done ? 1'd1; } group write30<"static"=1> { p30.write_en = write_en; l30.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l30.in = slice.out; p30.in = in; write30[done] = p30.done & l30.done ? 1'd1; } group write31<"static"=1> { p31.write_en = write_en; l31.write_en = write_en; sub.left = prefix_len; sub.right = 6'd1; slice.in = sub.out; l31.in = slice.out; p31.in = in; write31[done] = p31.done & l31.done ? 1'd1; } group find_write_index { is_index0.left = 5'd0; is_index1.left = 5'd1; is_index2.left = 5'd2; is_index3.left = 5'd3; is_index4.left = 5'd4; is_index5.left = 5'd5; is_index6.left = 5'd6; is_index7.left = 5'd7; is_index8.left = 5'd8; is_index9.left = 5'd9; is_index10.left = 5'd10; is_index11.left = 5'd11; is_index12.left = 5'd12; is_index13.left = 5'd13; is_index14.left = 5'd14; is_index15.left = 5'd15; is_index16.left = 5'd16; is_index17.left = 5'd17; is_index18.left = 5'd18; is_index19.left = 5'd19; is_index20.left = 5'd20; is_index21.left = 5'd21; is_index22.left = 5'd22; is_index23.left = 5'd23; is_index24.left = 5'd24; is_index25.left = 5'd25; is_index26.left = 5'd26; is_index27.left = 5'd27; is_index28.left = 5'd28; is_index29.left = 5'd29; is_index30.left = 5'd30; is_index31.left = 5'd31; is_index0.right = write_index; is_index1.right = write_index; is_index2.right = write_index; is_index3.right = write_index; is_index4.right = write_index; is_index5.right = write_index; is_index6.right = write_index; is_index7.right = write_index; is_index8.right = write_index; is_index9.right = write_index; is_index10.right = write_index; is_index11.right = write_index; is_index12.right = write_index; is_index13.right = write_index; is_index14.right = write_index; is_index15.right = write_index; is_index16.right = write_index; is_index17.right = write_index; is_index18.right = write_index; is_index19.right = write_index; is_index20.right = write_index; is_index21.right = write_index; is_index22.right = write_index; is_index23.right = write_index; is_index24.right = write_index; is_index25.right = write_index; is_index26.right = write_index; is_index27.right = write_index; is_index28.right = write_index; is_index29.right = write_index; is_index30.right = write_index; is_index31.right = write_index; comb_reg0.in = is_index0.out; comb_reg0.write_en = 1'd1; comb_reg1.in = is_index1.out; comb_reg1.write_en = 1'd1; comb_reg2.in = is_index2.out; comb_reg2.write_en = 1'd1; comb_reg3.in = is_index3.out; comb_reg3.write_en = 1'd1; comb_reg4.in = is_index4.out; comb_reg4.write_en = 1'd1; comb_reg5.in = is_index5.out; comb_reg5.write_en = 1'd1; comb_reg6.in = is_index6.out; comb_reg6.write_en = 1'd1; comb_reg7.in = is_index7.out; comb_reg7.write_en = 1'd1; comb_reg8.in = is_index8.out; comb_reg8.write_en = 1'd1; comb_reg9.in = is_index9.out; comb_reg9.write_en = 1'd1; comb_reg10.in = is_index10.out; comb_reg10.write_en = 1'd1; comb_reg11.in = is_index11.out; comb_reg11.write_en = 1'd1; comb_reg12.in = is_index12.out; comb_reg12.write_en = 1'd1; comb_reg13.in = is_index13.out; comb_reg13.write_en = 1'd1; comb_reg14.in = is_index14.out; comb_reg14.write_en = 1'd1; comb_reg15.in = is_index15.out; comb_reg15.write_en = 1'd1; comb_reg16.in = is_index16.out; comb_reg16.write_en = 1'd1; comb_reg17.in = is_index17.out; comb_reg17.write_en = 1'd1; comb_reg18.in = is_index18.out; comb_reg18.write_en = 1'd1; comb_reg19.in = is_index19.out; comb_reg19.write_en = 1'd1; comb_reg20.in = is_index20.out; comb_reg20.write_en = 1'd1; comb_reg21.in = is_index21.out; comb_reg21.write_en = 1'd1; comb_reg22.in = is_index22.out; comb_reg22.write_en = 1'd1; comb_reg23.in = is_index23.out; comb_reg23.write_en = 1'd1; comb_reg24.in = is_index24.out; comb_reg24.write_en = 1'd1; comb_reg25.in = is_index25.out; comb_reg25.write_en = 1'd1; comb_reg26.in = is_index26.out; comb_reg26.write_en = 1'd1; comb_reg27.in = is_index27.out; comb_reg27.write_en = 1'd1; comb_reg28.in = is_index28.out; comb_reg28.write_en = 1'd1; comb_reg29.in = is_index29.out; comb_reg29.write_en = 1'd1; comb_reg30.in = is_index30.out; comb_reg30.write_en = 1'd1; comb_reg31.in = is_index31.out; comb_reg31.write_en = 1'd1; find_write_index[done] = comb_reg0.done; } group default_to_zero_length_index<"static"=1> { out.write_en = 1'd1; out.in = zero_index.out; default_to_zero_length_index[done] = out.done; } group save_index<"static"=1> { out.write_en = 1'd1; out.in = ce40.addrX; save_index[done] = out.done; } index = out.out; } control { write_write_en_reg; write_search_en_reg; par { if write_en_reg.out { if z_eq.out with is_length_zero { write_zero; } else { seq { find_write_index; par { if comb_reg0.out { write0; } if comb_reg1.out { write1; } if comb_reg2.out { write2; } if comb_reg3.out { write3; } if comb_reg4.out { write4; } if comb_reg5.out { write5; } if comb_reg6.out { write6; } if comb_reg7.out { write7; } if comb_reg8.out { write8; } if comb_reg9.out { write9; } if comb_reg10.out { write10; } if comb_reg11.out { write11; } if comb_reg12.out { write12; } if comb_reg13.out { write13; } if comb_reg14.out { write14; } if comb_reg15.out { write15; } if comb_reg16.out { write16; } if comb_reg17.out { write17; } if comb_reg18.out { write18; } if comb_reg19.out { write19; } if comb_reg20.out { write20; } if comb_reg21.out { write21; } if comb_reg22.out { write22; } if comb_reg23.out { write23; } if comb_reg24.out { write24; } if comb_reg25.out { write25; } if comb_reg26.out { write26; } if comb_reg27.out { write27; } if comb_reg28.out { write28; } if comb_reg29.out { write29; } if comb_reg30.out { write30; } if comb_reg31.out { write31; } } } } } if search_en_reg.out { seq { par { invoke me0(in=in, prefix=p0.out, length=l0.out)(); invoke me1(in=in, prefix=p1.out, length=l1.out)(); invoke me2(in=in, prefix=p2.out, length=l2.out)(); invoke me3(in=in, prefix=p3.out, length=l3.out)(); invoke me4(in=in, prefix=p4.out, length=l4.out)(); invoke me5(in=in, prefix=p5.out, length=l5.out)(); invoke me6(in=in, prefix=p6.out, length=l6.out)(); invoke me7(in=in, prefix=p7.out, length=l7.out)(); invoke me8(in=in, prefix=p8.out, length=l8.out)(); invoke me9(in=in, prefix=p9.out, length=l9.out)(); invoke me10(in=in, prefix=p10.out, length=l10.out)(); invoke me11(in=in, prefix=p11.out, length=l11.out)(); invoke me12(in=in, prefix=p12.out, length=l12.out)(); invoke me13(in=in, prefix=p13.out, length=l13.out)(); invoke me14(in=in, prefix=p14.out, length=l14.out)(); invoke me15(in=in, prefix=p15.out, length=l15.out)(); invoke me16(in=in, prefix=p16.out, length=l16.out)(); invoke me17(in=in, prefix=p17.out, length=l17.out)(); invoke me18(in=in, prefix=p18.out, length=l18.out)(); invoke me19(in=in, prefix=p19.out, length=l19.out)(); invoke me20(in=in, prefix=p20.out, length=l20.out)(); invoke me21(in=in, prefix=p21.out, length=l21.out)(); invoke me22(in=in, prefix=p22.out, length=l22.out)(); invoke me23(in=in, prefix=p23.out, length=l23.out)(); invoke me24(in=in, prefix=p24.out, length=l24.out)(); invoke me25(in=in, prefix=p25.out, length=l25.out)(); invoke me26(in=in, prefix=p26.out, length=l26.out)(); invoke me27(in=in, prefix=p27.out, length=l27.out)(); invoke me28(in=in, prefix=p28.out, length=l28.out)(); invoke me29(in=in, prefix=p29.out, length=l29.out)(); invoke me30(in=in, prefix=p30.out, length=l30.out)(); invoke me31(in=in, prefix=p31.out, length=l31.out)(); } par { invoke ce00(lenA=l0.out, lenB=l1.out, addrA=5'd0, addrB=5'd1, mlA=me0.out, mlB=me1.out)(); invoke ce01(lenA=l2.out, lenB=l3.out, addrA=5'd2, addrB=5'd3, mlA=me2.out, mlB=me3.out)(); invoke ce02(lenA=l4.out, lenB=l5.out, addrA=5'd4, addrB=5'd5, mlA=me4.out, mlB=me5.out)(); invoke ce03(lenA=l6.out, lenB=l7.out, addrA=5'd6, addrB=5'd7, mlA=me6.out, mlB=me7.out)(); invoke ce04(lenA=l8.out, lenB=l9.out, addrA=5'd8, addrB=5'd9, mlA=me8.out, mlB=me9.out)(); invoke ce05(lenA=l10.out, lenB=l11.out, addrA=5'd10, addrB=5'd11, mlA=me10.out, mlB=me11.out)(); invoke ce06(lenA=l12.out, lenB=l13.out, addrA=5'd12, addrB=5'd13, mlA=me12.out, mlB=me13.out)(); invoke ce07(lenA=l14.out, lenB=l15.out, addrA=5'd14, addrB=5'd15, mlA=me14.out, mlB=me15.out)(); invoke ce08(lenA=l16.out, lenB=l17.out, addrA=5'd16, addrB=5'd17, mlA=me16.out, mlB=me17.out)(); invoke ce09(lenA=l18.out, lenB=l19.out, addrA=5'd18, addrB=5'd19, mlA=me18.out, mlB=me19.out)(); invoke ce010(lenA=l20.out, lenB=l21.out, addrA=5'd20, addrB=5'd21, mlA=me20.out, mlB=me21.out)(); invoke ce011(lenA=l22.out, lenB=l23.out, addrA=5'd22, addrB=5'd23, mlA=me22.out, mlB=me23.out)(); invoke ce012(lenA=l24.out, lenB=l25.out, addrA=5'd24, addrB=5'd25, mlA=me24.out, mlB=me25.out)(); invoke ce013(lenA=l26.out, lenB=l27.out, addrA=5'd26, addrB=5'd27, mlA=me26.out, mlB=me27.out)(); invoke ce014(lenA=l28.out, lenB=l29.out, addrA=5'd28, addrB=5'd29, mlA=me28.out, mlB=me29.out)(); invoke ce015(lenA=l30.out, lenB=l31.out, addrA=5'd30, addrB=5'd31, mlA=me30.out, mlB=me31.out)(); } par { invoke ce10(lenA=ce00.lenX, lenB=ce01.lenX, addrA=ce00.addrX, addrB=ce01.addrX, mlA=ce00.mlX, mlB=ce01.mlX)(); invoke ce11(lenA=ce02.lenX, lenB=ce03.lenX, addrA=ce02.addrX, addrB=ce03.addrX, mlA=ce02.mlX, mlB=ce03.mlX)(); invoke ce12(lenA=ce04.lenX, lenB=ce05.lenX, addrA=ce04.addrX, addrB=ce05.addrX, mlA=ce04.mlX, mlB=ce05.mlX)(); invoke ce13(lenA=ce06.lenX, lenB=ce07.lenX, addrA=ce06.addrX, addrB=ce07.addrX, mlA=ce06.mlX, mlB=ce07.mlX)(); invoke ce14(lenA=ce08.lenX, lenB=ce09.lenX, addrA=ce08.addrX, addrB=ce09.addrX, mlA=ce08.mlX, mlB=ce09.mlX)(); invoke ce15(lenA=ce010.lenX, lenB=ce011.lenX, addrA=ce010.addrX, addrB=ce011.addrX, mlA=ce010.mlX, mlB=ce011.mlX)(); invoke ce16(lenA=ce012.lenX, lenB=ce013.lenX, addrA=ce012.addrX, addrB=ce013.addrX, mlA=ce012.mlX, mlB=ce013.mlX)(); invoke ce17(lenA=ce014.lenX, lenB=ce015.lenX, addrA=ce014.addrX, addrB=ce015.addrX, mlA=ce014.mlX, mlB=ce015.mlX)(); } par { invoke ce20(lenA=ce10.lenX, lenB=ce11.lenX, addrA=ce10.addrX, addrB=ce11.addrX, mlA=ce10.mlX, mlB=ce11.mlX)(); invoke ce21(lenA=ce12.lenX, lenB=ce13.lenX, addrA=ce12.addrX, addrB=ce13.addrX, mlA=ce12.mlX, mlB=ce13.mlX)(); invoke ce22(lenA=ce14.lenX, lenB=ce15.lenX, addrA=ce14.addrX, addrB=ce15.addrX, mlA=ce14.mlX, mlB=ce15.mlX)(); invoke ce23(lenA=ce16.lenX, lenB=ce17.lenX, addrA=ce16.addrX, addrB=ce17.addrX, mlA=ce16.mlX, mlB=ce17.mlX)(); } par { invoke ce30(lenA=ce20.lenX, lenB=ce21.lenX, addrA=ce20.addrX, addrB=ce21.addrX, mlA=ce20.mlX, mlB=ce21.mlX)(); invoke ce31(lenA=ce22.lenX, lenB=ce23.lenX, addrA=ce22.addrX, addrB=ce23.addrX, mlA=ce22.mlX, mlB=ce23.mlX)(); } invoke ce40(lenA=ce30.lenX, lenB=ce31.lenX, addrA=ce30.addrX, addrB=ce31.addrX, mlA=ce30.mlX, mlB=ce31.mlX)(); write_ce40_reg; // If the final comparator has a valid value then save it. if ce40_reg.out { save_index; } else { default_to_zero_length_index; } } } } } }