1
+ /* *
2
+ * Copyright (c) 2022 Seyed Alireza Damghani ([email protected] )
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person
5
+ * obtaining a copy of this software and associated documentation
6
+ * files (the "Software"), to deal in the Software without
7
+ * restriction, including without limitation the rights to use,
8
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the
10
+ * Software is furnished to do so, subject to the following
11
+ * conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ * OTHER DEALINGS IN THE SOFTWARE.
24
+ *
25
+ * @file: This file provides utilities to modify the bitwise nodes
26
+ * to make them compatible with the Odin-II partial mapper.
27
+ */
28
+
29
+ #include < cmath> // log2
30
+ #include " BitwiseOps.hpp"
31
+ #include " node_creation_library.h"
32
+ #include " odin_util.h"
33
+ #include " netlist_utils.h"
34
+ #include " vtr_memory.h"
35
+
36
+ /* *
37
+ * (function: decode_bitwise_nodes)
38
+ *
39
+ * @brief decoding bitwise nodes into 2 inputs - 1 output nodes
40
+ *
41
+ * @param node pointing to a bitwise node
42
+ * @param traverse_mark_number unique traversal mark for blif elaboration pass
43
+ * @param netlist pointer to the current netlist file
44
+ */
45
+ void decode_bitwise_nodes (nnode_t * node, uintptr_t traverse_mark_number, netlist_t * /* netlist */ ) {
46
+ oassert (node->traverse_visited == traverse_mark_number);
47
+ oassert (node->num_input_port_sizes < 3 );
48
+ oassert (node->num_output_port_sizes == 1 );
49
+ oassert (node->num_output_pins == 1 );
50
+
51
+ // already satisfied the partial mapper requirement
52
+ if (node->num_input_pins < 3 || node->num_input_port_sizes == 2 )
53
+ return ;
54
+
55
+ int i, j;
56
+ /* keep the record of primary node info */
57
+ int width = node->input_port_sizes [0 ];
58
+ int levels = std::ceil (std::log2 (width));
59
+
60
+ /* *
61
+ *************************************************************************************************
62
+ * *
63
+ * |\ *
64
+ * N bit | \ 1 bit *
65
+ * in --'--> | | ----'----> *
66
+ * | / *
67
+ * |/ *
68
+ * *
69
+ ***************************************** <decoded nodes> ***************************************
70
+ * *
71
+ * *
72
+ * |\ *
73
+ * 2 bits | \ *
74
+ * in --'-- | | -- *
75
+ * | / |\ *
76
+ * |/ 2 bits | \ *
77
+ * --'-- | | -- *
78
+ * |\ | / *
79
+ * 2 bits | \ |/ *
80
+ * in --'-- | | -- *
81
+ * | / |\ *
82
+ * |/ 2 bits | \ *
83
+ * --'-- | | -- *
84
+ * |\ | / *
85
+ * 2 bits | \ |/ *
86
+ * in --'-- | | -- *
87
+ * | / |\ *
88
+ * |/ 2 bits | \ *
89
+ * --'-- | | -- *
90
+ * |\ | / *
91
+ * 2 bits | \ |/ *
92
+ * in --'-- | | -- *
93
+ * | / *
94
+ * |/ *
95
+ * *
96
+ * ... ... ... *
97
+ * *
98
+ * ... ... ... *
99
+ * *
100
+ * ... ... ... *
101
+ *************************************************************************************************/
102
+
103
+ nnode_t *** decoded_nodes = (nnode_t ***)vtr::calloc (levels, sizeof (nnode_t **));
104
+ /* to keep the internal input signals for future usage */
105
+ signal_list_t ** input_signals = (signal_list_t **)vtr::calloc (levels + 1 , sizeof (signal_list_t *));
106
+
107
+ /* init the first input signals with the primary node input signals */
108
+ input_signals[0 ] = init_signal_list ();
109
+ for (i = 0 ; i < width; ++i)
110
+ add_pin_to_signal_list (input_signals[0 ], node->input_pins [i]);
111
+
112
+ /* creating multiple stages to decode bitwise nodes into 2-1 nodes */
113
+ for (i = 0 ; i < levels; ++i) {
114
+ /* num of nodes in each stage */
115
+ int num_of_nodes = width / 2 ;
116
+ decoded_nodes[i] = (nnode_t **)vtr::calloc (num_of_nodes, sizeof (nnode_t *));
117
+ input_signals[i + 1 ] = init_signal_list ();
118
+
119
+ /* iterating over each decoded node to connect inputs */
120
+ for (j = 0 ; j < num_of_nodes; ++j) {
121
+ /* ****************************************************************************************
122
+ * <Bitwise Node> *
123
+ * *
124
+ * Port 1 *
125
+ * 0: in1 |\ *
126
+ * 1: in2 1 bit | \ *
127
+ * in1 --'--> | | 1 bit *
128
+ * | |---'---> *
129
+ * in2 --'--> | | *
130
+ * | / *
131
+ * |/ *
132
+ ****************************************************************************************/
133
+ decoded_nodes[i][j] = make_1port_gate (node->type , 2 , 1 , node, traverse_mark_number);
134
+
135
+ if (input_signals[i]->pins [2 * j]->node )
136
+ remap_pin_to_new_node (input_signals[i]->pins [2 * j], decoded_nodes[i][j], 0 );
137
+ else
138
+ add_input_pin_to_node (decoded_nodes[i][j], input_signals[i]->pins [2 * j], 0 );
139
+
140
+ if (input_signals[i]->pins [2 * j + 1 ]->node )
141
+ remap_pin_to_new_node (input_signals[i]->pins [2 * j + 1 ], decoded_nodes[i][j], 1 );
142
+ else
143
+ add_input_pin_to_node (decoded_nodes[i][j], input_signals[i]->pins [2 * j + 1 ], 1 );
144
+
145
+ // Connect output pin to related input pin
146
+ if (i != levels - 1 ) {
147
+ npin_t * new_pin1 = allocate_npin ();
148
+ npin_t * new_pin2 = allocate_npin ();
149
+ nnet_t * new_net = allocate_nnet ();
150
+ new_net->name = make_full_ref_name (NULL , NULL , NULL , decoded_nodes[i][j]->name , -1 );
151
+ /* hook the output pin into the node */
152
+ add_output_pin_to_node (decoded_nodes[i][j], new_pin1, 0 );
153
+ /* hook up new pin 1 into the new net */
154
+ add_driver_pin_to_net (new_net, new_pin1);
155
+ /* hook up the new pin 2 to this new net */
156
+ add_fanout_pin_to_net (new_net, new_pin2);
157
+
158
+ // Storing the output pins of the current node as the input of the next one
159
+ add_pin_to_signal_list (input_signals[i + 1 ], new_pin2);
160
+
161
+ } else {
162
+ remap_pin_to_new_node (node->output_pins [0 ], decoded_nodes[i][j], 0 );
163
+ }
164
+ }
165
+ /* in case we have odd width, move the last pin to next level */
166
+ if (width - 2 * j > 0 ) {
167
+ oassert (width - 2 * j < 2 );
168
+ add_pin_to_signal_list (input_signals[i + 1 ], input_signals[i]->pins [width - 1 ]);
169
+ }
170
+ width = input_signals[i + 1 ]->count ;
171
+ }
172
+
173
+ // CLEAN UP
174
+ for (i = 0 ; i < levels; i++) {
175
+ vtr::free (decoded_nodes[i]);
176
+ }
177
+ vtr::free (decoded_nodes);
178
+
179
+ for (i = 0 ; i < levels + 1 ; i++) {
180
+ free_signal_list (input_signals[i]);
181
+ }
182
+ vtr::free (input_signals);
183
+
184
+ // to free primary node
185
+ free_nnode (node);
186
+ }
0 commit comments