yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
macc.h
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 #ifndef MACC_H
21 #define MACC_H
22 
23 #include "kernel/yosys.h"
24 
26 
27 struct Macc
28 {
29  struct port_t {
32  };
33 
34  std::vector<port_t> ports;
36 
37  void optimize(int width)
38  {
39  std::vector<port_t> new_ports;
40  RTLIL::SigSpec new_bit_ports;
41  RTLIL::Const off(0, width);
42 
43  for (auto &port : ports)
44  {
45  if (GetSize(port.in_a) == 0 && GetSize(port.in_b) == 0)
46  continue;
47 
48  if (GetSize(port.in_a) < GetSize(port.in_b))
49  std::swap(port.in_a, port.in_b);
50 
51  if (GetSize(port.in_a) == 1 && GetSize(port.in_b) == 0 && !port.is_signed && !port.do_subtract) {
52  bit_ports.append(port.in_a);
53  continue;
54  }
55 
56  if (port.in_a.is_fully_const() && port.in_b.is_fully_const()) {
57  RTLIL::Const v = port.in_a.as_const();
58  if (GetSize(port.in_b))
59  v = const_mul(v, port.in_b.as_const(), port.is_signed, port.is_signed, width);
60  if (port.do_subtract)
61  off = const_sub(off, v, port.is_signed, port.is_signed, width);
62  else
63  off = const_add(off, v, port.is_signed, port.is_signed, width);
64  continue;
65  }
66 
67  if (port.is_signed) {
68  while (GetSize(port.in_a) > 1 && port.in_a[GetSize(port.in_a)-1] == port.in_a[GetSize(port.in_a)-2])
69  port.in_a.remove(GetSize(port.in_a)-1);
70  while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == port.in_b[GetSize(port.in_b)-2])
71  port.in_b.remove(GetSize(port.in_b)-1);
72  } else {
73  while (GetSize(port.in_a) > 1 && port.in_a[GetSize(port.in_a)-1] == RTLIL::S0)
74  port.in_a.remove(GetSize(port.in_a)-1);
75  while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == RTLIL::S0)
76  port.in_b.remove(GetSize(port.in_b)-1);
77  }
78 
79  new_ports.push_back(port);
80  }
81 
82  for (auto &bit : bit_ports)
83  if (bit == RTLIL::S1)
84  off = const_add(off, RTLIL::Const(1, width), false, false, width);
85  else if (bit != RTLIL::S0)
86  new_bit_ports.append(bit);
87 
88  if (off.as_bool()) {
89  port_t port;
90  port.in_a = off;
91  port.is_signed = false;
92  port.do_subtract = false;
93  new_ports.push_back(port);
94  }
95 
96  new_ports.swap(ports);
97  bit_ports = new_bit_ports;
98  }
99 
100  void from_cell(RTLIL::Cell *cell)
101  {
102  RTLIL::SigSpec port_a = cell->getPort("\\A");
103 
104  ports.clear();
105  bit_ports = cell->getPort("\\B");
106 
107  std::vector<RTLIL::State> config_bits = cell->getParam("\\CONFIG").bits;
108  int config_width = cell->getParam("\\CONFIG_WIDTH").as_int();
109  int config_cursor = 0;
110 
111  log_assert(GetSize(config_bits) >= config_width);
112 
113  int num_bits = 0;
114  if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 1;
115  if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 2;
116  if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 4;
117  if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 8;
118 
119  int port_a_cursor = 0;
120  while (port_a_cursor < GetSize(port_a))
121  {
122  log_assert(config_cursor + 2 + 2*num_bits <= config_width);
123 
124  port_t this_port;
125  this_port.is_signed = config_bits[config_cursor++] == RTLIL::S1;
126  this_port.do_subtract = config_bits[config_cursor++] == RTLIL::S1;
127 
128  int size_a = 0;
129  for (int i = 0; i < num_bits; i++)
130  if (config_bits[config_cursor++] == RTLIL::S1)
131  size_a |= 1 << i;
132 
133  this_port.in_a = port_a.extract(port_a_cursor, size_a);
134  port_a_cursor += size_a;
135 
136  int size_b = 0;
137  for (int i = 0; i < num_bits; i++)
138  if (config_bits[config_cursor++] == RTLIL::S1)
139  size_b |= 1 << i;
140 
141  this_port.in_b = port_a.extract(port_a_cursor, size_b);
142  port_a_cursor += size_b;
143 
144  if (size_a || size_b)
145  ports.push_back(this_port);
146  }
147 
148  log_assert(config_cursor == config_width);
149  log_assert(port_a_cursor == GetSize(port_a));
150  }
151 
152  void to_cell(RTLIL::Cell *cell) const
153  {
154  RTLIL::SigSpec port_a;
155  std::vector<RTLIL::State> config_bits;
156  int max_size = 0, num_bits = 0;
157 
158  for (auto &port : ports) {
159  max_size = std::max(max_size, GetSize(port.in_a));
160  max_size = std::max(max_size, GetSize(port.in_b));
161  }
162 
163  while (max_size)
164  num_bits++, max_size /= 2;
165 
166  log_assert(num_bits < 16);
167  config_bits.push_back(num_bits & 1 ? RTLIL::S1 : RTLIL::S0);
168  config_bits.push_back(num_bits & 2 ? RTLIL::S1 : RTLIL::S0);
169  config_bits.push_back(num_bits & 4 ? RTLIL::S1 : RTLIL::S0);
170  config_bits.push_back(num_bits & 8 ? RTLIL::S1 : RTLIL::S0);
171 
172  for (auto &port : ports)
173  {
174  if (GetSize(port.in_a) == 0)
175  continue;
176 
177  config_bits.push_back(port.is_signed ? RTLIL::S1 : RTLIL::S0);
178  config_bits.push_back(port.do_subtract ? RTLIL::S1 : RTLIL::S0);
179 
180  int size_a = GetSize(port.in_a);
181  for (int i = 0; i < num_bits; i++)
182  config_bits.push_back(size_a & (1 << i) ? RTLIL::S1 : RTLIL::S0);
183 
184  int size_b = GetSize(port.in_b);
185  for (int i = 0; i < num_bits; i++)
186  config_bits.push_back(size_b & (1 << i) ? RTLIL::S1 : RTLIL::S0);
187 
188  port_a.append(port.in_a);
189  port_a.append(port.in_b);
190  }
191 
192  cell->setPort("\\A", port_a);
193  cell->setPort("\\B", bit_ports);
194  cell->setParam("\\CONFIG", config_bits);
195  cell->setParam("\\CONFIG_WIDTH", GetSize(config_bits));
196  cell->setParam("\\A_WIDTH", GetSize(port_a));
197  cell->setParam("\\B_WIDTH", GetSize(bit_ports));
198  }
199 
200  bool eval(RTLIL::Const &result) const
201  {
202  for (auto &bit : result.bits)
203  bit = RTLIL::S0;
204 
205  for (auto &port : ports)
206  {
207  if (!port.in_a.is_fully_const() || !port.in_b.is_fully_const())
208  return false;
209 
210  RTLIL::Const summand;
211  if (GetSize(port.in_b) == 0)
212  summand = const_pos(port.in_a.as_const(), port.in_b.as_const(), port.is_signed, port.is_signed, GetSize(result));
213  else
214  summand = const_mul(port.in_a.as_const(), port.in_b.as_const(), port.is_signed, port.is_signed, GetSize(result));
215 
216  if (port.do_subtract)
217  result = const_sub(result, summand, port.is_signed, port.is_signed, GetSize(result));
218  else
219  result = const_add(result, summand, port.is_signed, port.is_signed, GetSize(result));
220  }
221 
222  for (auto bit : bit_ports) {
223  if (bit.wire)
224  return false;
225  result = const_add(result, bit.data, false, false, GetSize(result));
226  }
227 
228  return true;
229  }
230 
231  Macc(RTLIL::Cell *cell = nullptr)
232  {
233  if (cell != nullptr)
234  from_cell(cell);
235  }
236 };
237 
239 
240 #endif
void to_cell(RTLIL::Cell *cell) const
Definition: macc.h:152
bool as_bool() const
Definition: rtlil.cc:96
RTLIL::SigSpec bit_ports
Definition: macc.h:35
Definition: macc.h:27
void setParam(RTLIL::IdString paramname, RTLIL::Const value)
Definition: rtlil.cc:1829
#define YOSYS_NAMESPACE_END
Definition: yosys.h:100
bool eval(RTLIL::Const &result) const
Definition: macc.h:200
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
RTLIL::Const const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:471
std::vector< port_t > ports
Definition: macc.h:34
void optimize(int width)
Definition: macc.h:37
RTLIL::Const const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:478
RTLIL::SigSpec in_b
Definition: macc.h:30
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1809
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
#define log_assert(_assert_expr_)
Definition: log.h:85
void from_cell(RTLIL::Cell *cell)
Definition: macc.h:100
bool is_signed
Definition: macc.h:31
int as_int(bool is_signed=false) const
Definition: rtlil.cc:104
RTLIL::SigSpec in_a
Definition: macc.h:30
#define YOSYS_NAMESPACE_BEGIN
Definition: yosys.h:99
const RTLIL::Const & getParam(RTLIL::IdString paramname) const
Definition: rtlil.cc:1834
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
RTLIL::Const const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:464
Macc(RTLIL::Cell *cell=nullptr)
Definition: macc.h:231
bool do_subtract
Definition: macc.h:31
RTLIL::Const const_pos(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:562