@@ -45,6 +45,7 @@ PRIVATE_NAMESPACE_BEGIN
45
45
#define BLACKBOX_SIM_LIB_FILE cell_sim_blackbox.v
46
46
#define BLACKBOX_SIM_LIB_OFAB_FILE cell_ofab_sim_blackbox.v
47
47
#define SIM_LIB_CARRY_FILE CARRY.v
48
+ #define SIM_LIB_CARRY_BREAK_FILE CARRY_BREAK.v
48
49
#define LLATCHES_SIM_FILE llatches_sim.v
49
50
#define DSP_SIM_LIB_FILE dsp_sim.v
50
51
#define BRAMS_SIM_LIB_FILE brams_sim.v
@@ -5839,6 +5840,111 @@ static void show_sig(const RTLIL::SigSpec &sig)
5839
5840
}
5840
5841
}
5841
5842
5843
+ // We replace CARRY cells by CARRY_BREAK cells when we encounter carry chains
5844
+ // longer than 'max_carry_length'
5845
+ //
5846
+ // Return 1 if at least one break occured, 0 otherwise.
5847
+ //
5848
+ int insert_carry_chain_break_cells ()
5849
+ {
5850
+ int break_chain = 0 ;
5851
+
5852
+ dict<RTLIL::SigSpec, Cell *> ci2cell;
5853
+ dict<Cell *, RTLIL::SigSpec> co2cell;
5854
+ std::map<int , std::vector<Cell *>> carry_chains;
5855
+ vector<Cell *> carry_chain_head_cells;
5856
+
5857
+ for (auto cell : _design->top_module ()->cells ())
5858
+ {
5859
+ if (cell->type != RTLIL::escape_id (" CARRY" ))
5860
+ continue ;
5861
+
5862
+ // log("Cout = %s, CIN = %s\n",log_signal(cell->getPort(RTLIL::escape_id("COUT"))),log_signal(cell->getPort(RTLIL::escape_id("CIN"))));
5863
+ bool noCo = true ;
5864
+ for (auto &conn : cell->connections ())
5865
+ {
5866
+ IdString portName = conn.first ;
5867
+ RTLIL::SigSpec actual = conn.second ;
5868
+
5869
+ if (portName == RTLIL::escape_id (" CIN" ))
5870
+ {
5871
+ ci2cell[actual] = cell;
5872
+ continue ;
5873
+ }
5874
+
5875
+ if (portName == RTLIL::escape_id (" COUT" ) && !(actual.empty ()))
5876
+ {
5877
+ noCo = false ;
5878
+ co2cell[cell] = actual;
5879
+ continue ;
5880
+ }
5881
+ }
5882
+ if (noCo)
5883
+ {
5884
+ co2cell[cell] = {};
5885
+ carry_chain_head_cells.push_back (cell);
5886
+ }
5887
+ }
5888
+ vector<RTLIL::SigSpec> carry_chain_head_co2cell;
5889
+
5890
+ int chain = 0 ;
5891
+ for (auto head_cell : carry_chain_head_cells)
5892
+ {
5893
+ RTLIL::SigSpec signal = head_cell->getPort (RTLIL::escape_id (" CIN" ));
5894
+ chain += 1 ;
5895
+ carry_chains[chain].push_back (head_cell);
5896
+ while (!signal .empty ())
5897
+ {
5898
+ bool found = false ;
5899
+ for (auto &co_signal : co2cell)
5900
+ {
5901
+ if (co_signal.second == signal )
5902
+ {
5903
+ carry_chains[chain].push_back (co_signal.first );
5904
+ signal = co_signal.first ->getPort (RTLIL::escape_id (" CIN" ));
5905
+ found = true ;
5906
+ break ;
5907
+ }
5908
+ }
5909
+ if (!found)
5910
+ {
5911
+ break ;
5912
+ }
5913
+ }
5914
+ }
5915
+
5916
+ for (auto &chain : carry_chains)
5917
+ {
5918
+ std::vector<Cell*> original_chain = chain.second ;
5919
+
5920
+ int start = max_carry_length;
5921
+ int step = max_carry_length-2 ;
5922
+
5923
+ for (long unsigned int i = start; (i > 0 ) && (i < original_chain.size ()); i += step) {
5924
+
5925
+ Cell* previous_cell = original_chain[i-1 ];
5926
+ Cell* cell = original_chain[i];
5927
+
5928
+ if (previous_cell->type != RTLIL::escape_id (" CARRY" )) {
5929
+ continue ; // should never happen as cells are always CARRY
5930
+ }
5931
+ if (cell->type != RTLIL::escape_id (" CARRY" )) {
5932
+ continue ; // should never happen as cells are always CARRY
5933
+ }
5934
+
5935
+ // Every max length on the chain replace CARRY cell by a
5936
+ // CARRY_BREAK cell.
5937
+ //
5938
+ previous_cell->type = RTLIL::escape_id (" CARRY_BREAK" );
5939
+ log (" NOTE: Breaking carry chain at carry cell '%s'\n " ,
5940
+ (previous_cell->name ).c_str ());
5941
+ break_chain = 1 ;
5942
+ }
5943
+ }
5944
+
5945
+ return break_chain;
5946
+ }
5947
+
5842
5948
// Force 'keep' attribute on original IO BUF cells instantiated at RTL.
5843
5949
// (ex: EDA-3307 where one I_BUF is removed by optimizer because input is not used)
5844
5950
//
@@ -8449,6 +8555,42 @@ void collect_clocks (RTLIL::Module* module,
8449
8555
log_warning (" DSP exceeds the available DSP block limit (%d) on the device; the excess %d DSP blocks will be mapped to LUTs.\n " ,max_dsp, remaining_sum);
8450
8556
}
8451
8557
}
8558
+
8559
+ // We try to break long carry chains that exceed 'max_carry_length'
8560
+ //
8561
+ // 0. Extract all carry chains (use 'reportCarryChains' source code)
8562
+ // 1. replace CARRY cells by CARRY_BREAK cells every max_carry_length-2
8563
+ // 2. techmap CARRY_BREAK cells and replace them by verilog model
8564
+ // 3. clean up design after techmap
8565
+ //
8566
+ void break_carry_chains ()
8567
+ {
8568
+ // Performs 0. and 1.
8569
+ //
8570
+ int carry_breaks = insert_carry_chain_break_cells ();
8571
+
8572
+ if (!carry_breaks) {
8573
+ return ;
8574
+ }
8575
+
8576
+ log (" NOTE: after inserting carry chain break cells" );
8577
+ run (" stat" );
8578
+
8579
+ // Perform 2.
8580
+
8581
+ // string rreadArgs = GET_FILE_PATH(GENESIS_3_DIR, carry_break.v);
8582
+ string rreadArgs = GET_FILE_PATH_RS_FPGA_SIM (GENESIS_3_DIR, SIM_LIB_CARRY_BREAK_FILE);
8583
+
8584
+ // tech map the carry_break cells
8585
+ //
8586
+ run (stringf (" techmap -map %s " , rreadArgs.c_str ()));
8587
+
8588
+ // Perform 3.
8589
+ //
8590
+ run (" opt_clean -purge" );
8591
+
8592
+ log (" NOTE: after carry chain breaks" );
8593
+ }
8452
8594
8453
8595
void script () override
8454
8596
{
@@ -8984,8 +9126,13 @@ void collect_clocks (RTLIL::Module* module,
8984
9126
break ;
8985
9127
}
8986
9128
}
9129
+
9130
+ // We try to break long carry chains that exceed 'max_carry_length'
9131
+ //
9132
+ break_carry_chains ();
9133
+
8987
9134
run (" stat" );
8988
- break ;
9135
+ break ;
8989
9136
}
8990
9137
case Technologies::GENERIC: {
8991
9138
run (" techmap" );
0 commit comments