yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
blifparse.cc
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 #include "blifparse.h"
21 
23 
24 static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count, FILE *f)
25 {
26  int buffer_len = 0;
27  buffer[0] = 0;
28 
29  while (1)
30  {
31  buffer_len += strlen(buffer + buffer_len);
32  while (buffer_len > 0 && (buffer[buffer_len-1] == ' ' || buffer[buffer_len-1] == '\t' ||
33  buffer[buffer_len-1] == '\r' || buffer[buffer_len-1] == '\n'))
34  buffer[--buffer_len] = 0;
35 
36  if (buffer_size-buffer_len < 4096) {
37  buffer_size *= 2;
38  buffer = (char*)realloc(buffer, buffer_size);
39  }
40 
41  if (buffer_len == 0 || buffer[buffer_len-1] == '\\') {
42  if (buffer_len > 0 && buffer[buffer_len-1] == '\\')
43  buffer[--buffer_len] = 0;
44  line_count++;
45  if (fgets(buffer+buffer_len, buffer_size-buffer_len, f) == NULL)
46  return false;
47  } else
48  return true;
49  }
50 }
51 
52 RTLIL::Design *abc_parse_blif(FILE *f, std::string dff_name)
53 {
54  RTLIL::Design *design = new RTLIL::Design;
56 
57  RTLIL::Const *lutptr = NULL;
58  RTLIL::State lut_default_state = RTLIL::State::Sx;
59 
60  module->name = "\\netlist";
61  design->add(module);
62 
63  size_t buffer_size = 4096;
64  char *buffer = (char*)malloc(buffer_size);
65  int line_count = 0;
66 
67  while (1)
68  {
69  if (!read_next_line(buffer, buffer_size, line_count, f))
70  goto error;
71 
72  continue_without_read:
73  if (buffer[0] == '#')
74  continue;
75 
76  if (buffer[0] == '.')
77  {
78  if (lutptr) {
79  for (auto &bit : lutptr->bits)
80  if (bit == RTLIL::State::Sx)
81  bit = lut_default_state;
82  lutptr = NULL;
83  lut_default_state = RTLIL::State::Sx;
84  }
85 
86  char *cmd = strtok(buffer, " \t\r\n");
87 
88  if (!strcmp(cmd, ".model"))
89  continue;
90 
91  if (!strcmp(cmd, ".end")) {
92  module->fixup_ports();
93  free(buffer);
94  return design;
95  }
96 
97  if (!strcmp(cmd, ".inputs") || !strcmp(cmd, ".outputs")) {
98  char *p;
99  while ((p = strtok(NULL, " \t\r\n")) != NULL) {
100  RTLIL::Wire *wire = module->addWire(stringf("\\%s", p));
101  if (!strcmp(cmd, ".inputs"))
102  wire->port_input = true;
103  else
104  wire->port_output = true;
105  }
106  continue;
107  }
108 
109  if (!strcmp(cmd, ".latch"))
110  {
111  char *d = strtok(NULL, " \t\r\n");
112  char *q = strtok(NULL, " \t\r\n");
113 
114  if (module->wires_.count(RTLIL::escape_id(d)) == 0)
115  module->addWire(RTLIL::escape_id(d));
116 
117  if (module->wires_.count(RTLIL::escape_id(q)) == 0)
118  module->addWire(RTLIL::escape_id(q));
119 
120  RTLIL::Cell *cell = module->addCell(NEW_ID, dff_name);
121  cell->setPort("\\D", module->wires_.at(RTLIL::escape_id(d)));
122  cell->setPort("\\Q", module->wires_.at(RTLIL::escape_id(q)));
123  continue;
124  }
125 
126  if (!strcmp(cmd, ".gate"))
127  {
128  char *p = strtok(NULL, " \t\r\n");
129  if (p == NULL)
130  goto error;
131 
132  RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(p));
133 
134  while ((p = strtok(NULL, " \t\r\n")) != NULL) {
135  char *q = strchr(p, '=');
136  if (q == NULL || !q[0] || !q[1])
137  goto error;
138  *(q++) = 0;
139  if (module->wires_.count(RTLIL::escape_id(q)) == 0)
140  module->addWire(RTLIL::escape_id(q));
141  cell->setPort(RTLIL::escape_id(p), module->wires_.at(RTLIL::escape_id(q)));
142  }
143  continue;
144  }
145 
146  if (!strcmp(cmd, ".names"))
147  {
148  char *p;
149  RTLIL::SigSpec input_sig, output_sig;
150  while ((p = strtok(NULL, " \t\r\n")) != NULL) {
151  RTLIL::Wire *wire;
152  if (module->wires_.count(stringf("\\%s", p)) > 0) {
153  wire = module->wires_.at(stringf("\\%s", p));
154  } else {
155  wire = module->addWire(stringf("\\%s", p));
156  }
157  input_sig.append(wire);
158  }
159  output_sig = input_sig.extract(input_sig.size()-1, 1);
160  input_sig = input_sig.extract(0, input_sig.size()-1);
161 
162  if (input_sig.size() == 0) {
164  while (1) {
165  if (!read_next_line(buffer, buffer_size, line_count, f))
166  goto error;
167  for (int i = 0; buffer[i]; i++) {
168  if (buffer[i] == ' ' || buffer[i] == '\t')
169  continue;
170  if (i == 0 && buffer[i] == '.')
171  goto finished_parsing_constval;
172  if (buffer[i] == '0') {
173  if (state == RTLIL::State::S1)
174  goto error;
175  state = RTLIL::State::S0;
176  continue;
177  }
178  if (buffer[i] == '1') {
179  if (state == RTLIL::State::S0)
180  goto error;
181  state = RTLIL::State::S1;
182  continue;
183  }
184  goto error;
185  }
186  }
187  finished_parsing_constval:
188  if (state == RTLIL::State::Sa)
189  state = RTLIL::State::S1;
190  module->connect(RTLIL::SigSig(output_sig, state));
191  goto continue_without_read;
192  }
193 
194  RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut");
195  cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size());
196  cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size());
197  cell->setPort("\\A", input_sig);
198  cell->setPort("\\Y", output_sig);
199  lutptr = &cell->parameters.at("\\LUT");
200  lut_default_state = RTLIL::State::Sx;
201  continue;
202  }
203 
204  goto error;
205  }
206 
207  if (lutptr == NULL)
208  goto error;
209 
210  char *input = strtok(buffer, " \t\r\n");
211  char *output = strtok(NULL, " \t\r\n");
212 
213  if (input == NULL || output == NULL || (strcmp(output, "0") && strcmp(output, "1")))
214  goto error;
215 
216  int input_len = strlen(input);
217  if (input_len > 8)
218  goto error;
219 
220  for (int i = 0; i < (1 << input_len); i++) {
221  for (int j = 0; j < input_len; j++) {
222  char c1 = input[j];
223  if (c1 != '-') {
224  char c2 = (i & (1 << j)) != 0 ? '1' : '0';
225  if (c1 != c2)
226  goto try_next_value;
227  }
228  }
229  lutptr->bits.at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1;
230  try_next_value:;
231  }
232 
233  lut_default_state = !strcmp(output, "0") ? RTLIL::State::S1 : RTLIL::State::S0;
234  }
235 
236 error:
237  log_error("Syntax error in line %d!\n", line_count);
238  // delete design;
239  // return NULL;
240 }
241 
243 
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
void free(void *)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void add(RTLIL::Module *module)
Definition: rtlil.cc:259
void * malloc(YYSIZE_T)
#define YOSYS_NAMESPACE_END
Definition: yosys.h:100
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool port_input
Definition: rtlil.h:827
void log_error(const char *format,...)
Definition: log.cc:204
RTLIL::Module * module
Definition: abc.cc:94
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
int size() const
Definition: rtlil.h:1019
static std::string escape_id(std::string str)
Definition: rtlil.h:251
bool port_output
Definition: rtlil.h:827
RTLIL::Design * abc_parse_blif(FILE *f, std::string dff_name)
Definition: blifparse.cc:52
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
void fixup_ports()
Definition: rtlil.cc:1312
static YOSYS_NAMESPACE_BEGIN bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count, FILE *f)
Definition: blifparse.cc:24
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
RTLIL::IdString name
Definition: rtlil.h:599
#define NEW_ID
Definition: yosys.h:166
#define NULL
#define YOSYS_NAMESPACE_BEGIN
Definition: yosys.h:99
static int input(void)
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
State
Definition: rtlil.h:29
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71