CGRA-ME
AdresPE.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * The software programs comprising "CGRA-ME" and the documentation provided
3  * with them are copyright by its authors and the University of Toronto. Only
4  * non-commercial, not-for-profit use of this software is permitted without ex-
5  * plicit permission. This software is provided "as is" with no warranties or
6  * guarantees of support. See the LICENCE for more details. You should have re-
7  * ceived a copy of the full licence along with this software. If not, see
8  * <http://cgra-me.ece.utoronto.ca/license/>.
9  ******************************************************************************/
10 
12 #include <climits>
13 
14 std::string AdresPE::GenericName()
15 {
16  return "adres_" + std::to_string(num_inputs) + "in_" + fu_type;
17 }
18 
19 AdresPE::AdresPE(std::string name, int num_inputs_arg, std::string fu_type, int fu_II, int latency, int II, Location loc, bool use_op_div, bool predExist, bool reg_bypass, bool extra_mem, std::string pred_scheme)
20  : Module(name, loc)
21  , fu_type(fu_type)
22  , num_inputs(num_inputs_arg)
23 {
24  isElastic = false;
25  int size = 32;
26  // define op lists for types for functional units
27  using OpGraphVec = std::vector<OpGraphOpCode>;
28  std::map<std::string, OpGraphVec> fu_oplist;
29  fu_oplist["vliw"] = {
34  OpCode::OR,
39  OpCode::ICMP};
40  fu_oplist["cga"] = {
42  OpCode::SUB};
43 
44  if (use_op_div) fu_oplist["vliw"].push_back(OpCode::DIV);
45 
46  // Instantiate submodules
47  if (predExist && pred_scheme.find("event") == std::string::npos) {
48  addSubModule(new SelMultiplexer("mux_a", loc, num_inputs + 2), 0, 0, 0.5, 0.25); // mux for FU input "A" (+2 bc of const, rf)
49  addSubModule(new SelMultiplexer("mux_b", loc, num_inputs + 2), 0.5, 0, 0.5, 0.25);
50  addSubModule(new SelMultiplexer("mux_bypass", loc, num_inputs + 1), 0, 0.25, 0.5, 0.25);// bypass mux for all inputs
51  } else {
52  addSubModule(new Multiplexer("mux_a", loc, num_inputs + 2), 0, 0, 0.5, 0.25); // mux for FU input "A" (+2 bc of const, rf)
53  addSubModule(new Multiplexer("mux_b", loc, num_inputs + 2), 0.5, 0, 0.5, 0.25); // mux for FU input "B" (+2 bc of const, mux_out)
54  addSubModule(new Multiplexer("mux_bypass", loc, num_inputs), 0, 0.25, 0.5, 0.25);// bypass mux for all inputs
55  }
56  addSubModule(new ConstUnit("const_val", loc, 32, II), 0.5, 0.25, 0.5, 0.25); // const unit
57  addSubModule(new FuncUnit("func", loc, fu_oplist[fu_type], 32, fu_II, latency), 0, 0.5, 0.5, 0.25);// choose supported ops according to 'fu_type'
58  addSubModule(new Multiplexer("mux_out", loc, 2), 0.5, 0.5, 0.5, 0.25); // mux for output (choose bypass or fu)
59 
60  // Instantiate input & output ports
61  for(int i = 0; i < num_inputs; i++)
62  addPort("in" + std::to_string(i), PORT_INPUT, size);
63  addPort("out", PORT_OUTPUT, size);
64 
65  // Register file input & output ports
66  addPort("rf_to_muxa", PORT_INPUT, size); // input port for external RF into MUXA
67  addPort("rf_to_muxout", PORT_INPUT, size); // input port for external RF into MUX_OUT
68  addPort("fu_to_rf", PORT_OUTPUT, size); // output port for external RF from FU
69  if (reg_bypass) {
70  addPort("bypass_to_rf", PORT_OUTPUT, size); // output port for external RF from FU
71  }
72  if (II > 1)
73  addPort("Context", PORT_INPUT, ceil(log2(II)));
74 
75  // Instantiate configuration cells
76  addConfig(new ConfigCell("MuxAConfig", II), {"mux_a.select"});
77  addConfig(new ConfigCell("MuxBConfig", II), {"mux_b.select"});
78  addConfig(new ConfigCell("MuxBypassConfig", II), {"mux_bypass.select"});
79  addConfig(new ConfigCell("MuxOutConfig", II), {"mux_out.select"});
80  addConfig(new ConfigCell("FuncConfig", II), {"func.select"});
81  if (II > 1) {
82  addConnection("this.Context" , "MuxAConfig.Context", false);
83  addConnection("this.Context" , "MuxBConfig.Context", false);
84  addConnection("this.Context" , "MuxBypassConfig.Context", false);
85  addConnection("this.Context" , "MuxOutConfig.Context", false);
86  addConnection("this.Context" , "FuncConfig.Context", false);
87  addConnection("this.Context" , "const_val.Context", false);
88  }
89 
90  // Mux A connections
91  for(int i = 0; i < num_inputs; i++)
92  addConnection("this.in" + std::to_string(i), "mux_a.in" + std::to_string(i));
93 
94  addConnection("const_val.out", "mux_a.in" + std::to_string(num_inputs));
95  addConnection("this.rf_to_muxa", "mux_a.in" + std::to_string(num_inputs + 1)); // rf connected to one input
96  addConnection("mux_a.out", "func.in_a");
97 
98  // Mux B connections
99  for(int i = 0; i < num_inputs; i++)
100  addConnection("this.in" + std::to_string(i), "mux_b.in" + std::to_string(i));
101 
102  addConnection("const_val.out", "mux_b.in" + std::to_string(num_inputs));
103  if (predExist) {
104  addConnection("const_val.out", "mux_bypass.in" + std::to_string(num_inputs));
105  }
106  addConnection("mux_out.out", "mux_b.in" + std::to_string(num_inputs + 1));
107  addConnection("mux_b.out", "func.in_b");
108 
109  // BYPASS MUX CONNECTIONS
110  for(int i = 0; i < num_inputs; i++)
111  addConnection("this.in" + std::to_string(i), "mux_bypass.in" + std::to_string(i));
112  addConnection("mux_bypass.out", "mux_out.in1");
113 
114  // output muxing
115  addConnection("this.rf_to_muxout", "mux_out.in0");
116  addConnection("func.out", "this.fu_to_rf"); // connect registered output to rf
117  if (reg_bypass) {
118  addConnection("mux_bypass.out", "this.bypass_to_rf"); // connect registered output to rf
119  }
120  addConnection("mux_out.out", "this.out");
121 
122  if (!predExist) return;
123 
124  /****************** PRED NETWORK BEGINS **************/
125  /* The predication network is the same as the normal */
126  /* 32-bit architecture however it is a 1-bit wide n- */
127  /* etwork. */
128  /*****************************************************/
129 
130  bool top_pe = name.find("r0") != std::string::npos;
131  bool is_event_pred_scheme = pred_scheme.find("event") != std::string::npos;
132  addSubModule(new TruncateInput("trunc_res", loc, 1, size));
133  addSubModule(new TruncateInput("trunc_const", loc, 1, size));
134  size = 1;
135 
136  // define op lists for types for functional units
137  using OpGraphVec = std::vector<OpGraphOpCode>;
138  std::map<std::string, OpGraphVec> fu_oplist_pred;
139  fu_oplist_pred["pred"] = {
140  OpCode::AND,
141  OpCode::OR,
142  OpCode::XOR,
143  };
144 
145  // Instantiate submodules
146  addSubModule( new Multiplexer("mux_a_pred", loc, num_inputs + (2 - extra_mem), size), 0, 0, 0.5, 0.25); // mux for FU input "A" (+2 bc of const, rf)
147  addSubModule( new Multiplexer("mux_b_pred", loc, num_inputs + (2 - extra_mem), size), 0.5, 0, 0.5, 0.25); // mux for FU input "B" (+2 bc of const, mux_out)
148 
149  addSubModule(new Multiplexer("mux_bypass_pred", loc, num_inputs - extra_mem, size), 0, 0.25, 0.5, 0.25);// bypass mux for all inputs
150 
151  addSubModule(new FuncUnit("func_pred", loc, fu_oplist_pred["pred"], size, 1, latency), 0, 0.5, 0.5, 0.25);// choose supported ops according to 'fu_type'
152  addSubModule(new Multiplexer("mux_out_pred", loc, 2, size), 0.5, 0.5, 0.5, 0.25); // mux for output (choose bypass or fu)
153  addSubModule(new Multiplexer("mux_pred_out", loc, 4, size), 0.5, 0.5, 0.5, 0.25); // mux for output (choose bypass or fu)
154 
155  // Instantiate configuration cells
156  addConfig(new ConfigCell("MuxAConfigPred", II), {"mux_a_pred.select"});
157  addConfig(new ConfigCell("MuxBConfigPred", II), {"mux_b_pred.select"});
158  addConfig(new ConfigCell("MuxBypassConfigPred", II), {"mux_bypass_pred.select"});
159  addConfig(new ConfigCell("MuxPredOutraConfigPred", II), {"mux_pred_out.select"});
160  addConfig(new ConfigCell("MuxOutConfigPred", II), {"mux_out_pred.select"});
161  addConfig(new ConfigCell("FuncConfigPred", II), {"func_pred.select"});
162  if (II > 1) {
163  addConnection("this.Context" , "MuxAConfigPred.Context", false);
164  addConnection("this.Context" , "MuxBConfigPred.Context", false);
165  addConnection("this.Context" , "MuxBypassConfigPred.Context", false);
166  addConnection("this.Context" , "MuxOutConfigPred.Context", false);
167  addConnection("this.Context" , "FuncConfigPred.Context", false);
168  }
169 
170  // Instantiate input & output ports
171  for(int i = 0; i < num_inputs; i++){
172  if (i <= 0 + extra_mem) continue;
173  addPort("in_pred" + std::to_string(i), PORT_INPUT, size);
174  }
175  addPort("out_pred", PORT_OUTPUT, size);
176 
177  // Register file input & output ports
178  addPort("rf_to_muxa_pred", PORT_INPUT, size); // input port for external RF into MUXA
179  addPort("rf_to_muxout_pred", PORT_INPUT, size); // input port for external RF into MUX_OUT
180  addPort("fu_to_rf_pred", PORT_OUTPUT, size); // output port for external RF from FU
181  if (reg_bypass) {
182  addPort("bypass_to_rf_pred", PORT_OUTPUT, size); // output port for external RF from FU
183  }
184 
185  addConnection("mux_out.out", "trunc_res.in");
186  addConnection("const_val.out", "trunc_const.in");
187 
188  // Mux A connections
189  for(int i = 0; i < num_inputs; i++) {
190  if (i <= 0 + extra_mem) continue;
191  addConnection("this.in_pred" + std::to_string(i), "mux_a_pred.in" + std::to_string(i - (1 + extra_mem)));
192  }
193  addConnection("trunc_const.out0", "mux_a_pred.in" + std::to_string(num_inputs - (1 + extra_mem)));
194  addConnection("this.rf_to_muxa_pred", "mux_a_pred.in" + std::to_string(num_inputs - extra_mem)); // rf connected to one input
195  addConnection("trunc_res.out0", "mux_a_pred.in" + std::to_string(num_inputs + (1 - extra_mem)));
196  addConnection("mux_a_pred.out", "func_pred.in_a");
197  addConnection("mux_a_pred.out", "mux_pred_out.in0");
198 
199  // Mux B connections
200  for(int i = 0; i < num_inputs; i++) {
201  if (i <= 0 + extra_mem) continue;
202  addConnection("this.in_pred" + std::to_string(i), "mux_b_pred.in" + std::to_string(i- (1 + extra_mem)));
203  }
204 
205  addConnection("trunc_const.out0", "mux_b_pred.in" + std::to_string(num_inputs - (1+ extra_mem)));
206  addConnection("mux_out_pred.out", "mux_b_pred.in" + std::to_string(num_inputs - (extra_mem)));
207  addConnection("trunc_res.out0", "mux_b_pred.in" + std::to_string(num_inputs + (1 - extra_mem)));
208  addConnection("mux_b_pred.out", "func_pred.in_b");
209  addConnection("mux_b_pred.out", "mux_pred_out.in1");
210 
211  // BYPASS MUX CONNECTIONS
212  for(int i = 0; i < num_inputs; i++){
213  if (i <= 0 + extra_mem) continue;
214  addConnection("this.in_pred" + std::to_string(i), "mux_bypass_pred.in" + std::to_string(i - (1 + extra_mem)));
215  }
216  addConnection("trunc_res.out0", "mux_bypass_pred.in" + std::to_string(num_inputs - (1 + extra_mem)));
217  addConnection("mux_bypass_pred.out", "mux_out_pred.in1");
218  addConnection("mux_bypass_pred.out", "mux_pred_out.in2");
219 
220  // output muxing
221  addConnection("this.rf_to_muxout_pred", "mux_out_pred.in0");
222  addConnection("this.rf_to_muxout_pred", "mux_pred_out.in3");
223  addConnection("func_pred.out", "this.fu_to_rf_pred"); // connect registered output to
224  if (reg_bypass) {
225  addConnection("mux_bypass_pred.out", "this.bypass_to_rf_pred"); // connect registered output to rf
226  }
227  if (pred_scheme.find("event") == std::string::npos){
228  addConnection("mux_pred_out.out", "mux_b.selectpred"); // connect registered output to rf
229  addConnection("mux_pred_out.out", "mux_bypass.selectpred"); // connect registered output to rf
230  addConnection("mux_pred_out.out", "mux_a.selectpred"); // connect registered output to rf
231  }
232  addConnection("mux_out_pred.out", "this.out_pred");
233 }
234 
Module::name
std::string name
Definition: Module.h:341
ConfigCell
Definition: Module.h:825
OpCode::DIV
@ DIV
TruncateInput
Zero-cycle latency split input.
Definition: Module.h:621
Multiplexer
Zero-cycle latency multiplexer.
Definition: Module.h:592
Location
Definition: Module.h:156
OpCode::ASHR
@ ASHR
OpCode::OR
@ OR
Module::addConnection
void addConnection(std::string src, std::string dst, bool isInMRRG=true)
Definition: Module.cpp:1241
AdresPE::fu_type
std::string fu_type
Definition: UserModules.h:31
OpCode::ADD
@ ADD
Module::addPort
void addPort(std::string portname, port_type pt, unsigned size)
Definition: Module.cpp:1354
to_string
const std::string & to_string(const OpGraphOpCode &opcode)
Definition: OpGraph.cpp:111
OpCode::LSHR
@ LSHR
OpCode::XOR
@ XOR
AdresPE::AdresPE
AdresPE(std::string name, int num_inputs, std::string fu_type, int fu_II, int latency, int II, Location Loc, bool use_op_div=false, bool predExist=false, bool reg_bypass=false, bool extra_mem=false, std::string pred_scheme="")
Definition: AdresPE.cpp:19
AdresPE::num_inputs
int num_inputs
Definition: UserModules.h:32
UserModules.h
ConstUnit
Definition: Module.h:540
Module
Definition: Module.h:163
PORT_INPUT
@ PORT_INPUT
Definition: Module.h:63
OpCode::SHL
@ SHL
Module::addConfig
void addConfig(ConfigCell *c, std::vector< std::string > ConnectTo)
Definition: Module.cpp:1087
Module::addSubModule
void addSubModule(Module *m)
Definition: Module.cpp:1124
OpCode::AND
@ AND
Module::isElastic
bool isElastic
Definition: Module.h:236
OpCode::SUB
@ SUB
OpCode::MUL
@ MUL
Module::loc
Location loc
Definition: Module.h:239
SelMultiplexer
2 Zero-cycle latency multiplexers for predication support.
Definition: Module.h:647
OpCode::ICMP
@ ICMP
AdresPE::GenericName
virtual std::string GenericName()
Definition: AdresPE.cpp:14
FuncUnit
Functional Unit, does one of a set of arithmetic computations.
Definition: Module.h:406
PORT_OUTPUT
@ PORT_OUTPUT
Definition: Module.h:64