1use crate::primitives::*;
2use std::fs;
3use indexmap::IndexMap;
4
5type IResultStr<'a> = IResult<&'a str, &'a str>;
6
7use nom::{
8 bytes::complete::{is_not, tag, take_until},
9 combinator::value,
10 sequence::{pair, terminated},
11 IResult,
12};
13
14fn take_until_or_end<'a>(tag: &'a str, istr: &'a str) -> IResultStr<'a> {
15 let ret: IResult<&str, &str> = take_until(tag)(istr);
16 match ret {
17 Ok(x) => Ok(x),
18 Err(_) => Ok(("", istr)),
19 }
20}
21
22fn terminated_newline<'a>(istr: &'a str) -> IResultStr<'a> {
23 let ret: IResult<&str, &str> =
24 terminated(take_until("\n"), nom::character::complete::newline)(istr);
25 match ret {
26 Ok(x) => Ok(x),
27 Err(_) => Ok(("", istr)),
28 }
29}
30
31fn lut_table_parser<'a>(input: &'a str, table: &mut Vec<Vec<u8>>) -> IResultStr<'a> {
32 let mut i = input;
33 let mut li;
34 let mut te;
35 while i.len() > 0 {
36 (i, li) = terminated_newline(i)?;
37
38 let mut row: Vec<u8> = vec![];
39 let (_, mut table_input) = take_until(" ")(li)?;
40 while table_input.len() > 0 {
41 (table_input, te) = nom::character::complete::one_of("01")(table_input)?;
42 row.push(te.to_digit(10).unwrap() as u8);
43 }
44 table.push(row);
45 }
46 Ok(("", ""))
47}
48
49fn lut_body_parser<'a>(input: &'a str, luts: &mut Vec<ParsedPrimitive>) -> IResultStr<'a> {
50 let (i, ioline) = terminated_newline(input)?;
51 let mut io: Vec<&str> = ioline.split(' ').collect();
52
53 let output = io.pop().unwrap_or("INVALID_OUTPUT").to_string();
54 let inputs: Vec<String> = io.iter().map(|v| v.to_string()).collect();
55 let (i, table) = take_until_or_end(".", i)?;
56
57 let mut lut_table = vec![];
58 let _ = lut_table_parser(table, &mut lut_table);
59
60 luts.push(ParsedPrimitive::Lut {
61 inputs: inputs,
62 output: output,
63 table: lut_table
64 });
65
66 Ok((i, ""))
67}
68
69fn subckt_parser<'a>(input: &'a str, subckts: &mut Vec<ParsedPrimitive>) -> IResultStr<'a> {
70 let (i, sline) = terminated_newline(input)?;
71 let conns_vec: Vec<&str> = sline.split(' ').collect();
72 let name = conns_vec[0];
73
74 let mut conns = IndexMap::new();
75 conns_vec.iter().skip(1).for_each(|c| {
76 let lr: Vec<&str> = c.split('=').collect();
77 let lhs = lr[0];
78 let rhs = lr[1];
79 conns.insert(lhs.to_string(), rhs.to_string());
80 });
81
82 subckts.push(ParsedPrimitive::Subckt {
83 name: name.to_string(),
84 conns: conns,
85 });
86
87 Ok((i, ""))
88}
89
90fn gate_parser<'a>(input: &'a str, gates: &mut Vec<ParsedPrimitive>) -> IResultStr<'a> {
94 let (i, line) = terminated_newline(input)?;
95
96 let signal_conns: Vec<&str> = line.split(' ').collect();
97 let mut c = "".to_string();
98 let mut d = "".to_string();
99 let mut q = "".to_string();
100 let mut r = None;
101 let mut e = None;
102
103 for sc in signal_conns.iter() {
104 let x: Vec<&str> = sc.split('=').collect();
105 if x.len() != 2 {
106 continue;
107 }
108 match x[0] {
109 "C" => {
110 c = x[1].to_string();
111 }
112 "D" => {
113 d = x[1].to_string();
114 }
115 "Q" => {
116 q = x[1].to_string();
117 }
118 "R" => {
119 r = Some(x[1].to_string());
120 }
121 "E" => {
122 e = Some(x[1].to_string());
123 }
124 _ => {}
125 }
126 }
127
128 gates.push(ParsedPrimitive::Gate { c: c, d: d, q: q, r: r, e: e });
129 Ok((i, ""))
130}
131
132fn latch_parser<'a>(input: &'a str, latches: &mut Vec<ParsedPrimitive>) -> IResultStr<'a> {
133 let (i, line) = terminated_newline(input)?;
134 let latch_info: Vec<&str> = line.split(' ').collect();
135
136 let mut input = "".to_string();
137 let mut output = "".to_string();
138 let mut control = "".to_string();
139 let mut init = LatchInit::UNKNOWN;
140
141 for (idx, li) in latch_info.iter().enumerate() {
142 match idx {
143 0 => {
144 input = li.to_string();
145 }
146 1 => {
147 output = li.to_string();
148 }
149 3 => {
150 control = li.to_string();
151 }
152 4 => {
153 init = LatchInit::to_enum(li);
154 }
155 _ => {}
156 }
157 }
158 match init {
159 LatchInit::ONE =>
160 assert!(false, "Chisel RegInits changes the LUTs not the latch inputs"),
161 _ =>
162 ()
163 }
164 latches.push(ParsedPrimitive::Latch { input: input, output: output, control: control, init: init });
165 Ok((i, ""))
166}
167
168fn module_body_parser<'a>(input: &'a str, modules: &mut Vec<ParsedPrimitive>) -> IResultStr<'a> {
169 let body_end_marker = "\n.end\n";
170
171 let (i, _) = tag(".model ")(input)?;
173 let (i, name) = terminated(take_until("\n"), nom::character::complete::newline)(i)?;
174 let (mut i, body) = terminated(
175 take_until(body_end_marker),
176 nom::character::complete::newline,
177 )(i)?;
178
179 let (bi, iline) = terminated(take_until("\n"), nom::character::complete::newline)(body)?;
181 let inputs: Vec<String> = iline.split(' ').map(|v| v.to_string()).skip(1).collect();
182
183 let (bi, oline) = terminated(take_until("\n"), nom::character::complete::newline)(bi)?;
185 let outputs: Vec<String> = oline.split(' ').map(|v| v.to_string()).skip(1).collect();
186
187 let mut elems = vec![];
188 let mut bi = bi;
189 let mut tagstr;
190
191 while bi.len() > 1 {
192 (bi, tagstr) = terminated(take_until(" "), nom::character::complete::multispace0)(bi)?;
193 if tagstr.eq(".names") {
194 (bi, _) = lut_body_parser(bi, &mut elems)?;
195 } else if tagstr.eq(".subckt") {
196 (bi, _) = subckt_parser(bi, &mut elems)?;
197 } else if tagstr.eq(".gate") {
198 (bi, _) = gate_parser(bi, &mut elems)?;
199 } else if tagstr.eq(".latch") {
200 (bi, _) = latch_parser(bi, &mut elems)?;
201 }
202 }
203
204 if i.len() > body_end_marker.to_string().len() {
205 (i, _) = take_until(".")(i)?;
207 } else {
208 (i, _) = take_until("\n")(i)?;
210 }
211
212 modules.push(ParsedPrimitive::Module {
213 name: name.to_string(),
214 inputs: inputs,
215 outputs: outputs,
216 elems: elems
217 });
218
219 Ok((i, ""))
220}
221
222fn parse_modules_from_blif_str<'a>(input: &'a str, circuit: &mut Vec<ParsedPrimitive>) -> IResultStr<'a> {
223 let (i, _) = value((), pair(tag("#"), is_not("\n")))(input)?;
225 let (i, _) = take_until(".")(i)?;
226
227 let mut i = i;
228 while i.len() > 4 {
229 (i, _) = module_body_parser(i, circuit)?;
230 (i, _) = take_until_or_end("\n.model", i)?;
231 (i, _) = terminated_newline(i)?;
232 }
233
234 Ok(("", ""))
235}
236
237fn parse_blif(input: &str) -> Result<Vec<ParsedPrimitive>, String> {
238 let mut circuit = vec![];
239 let res = parse_modules_from_blif_str(input, &mut circuit);
240 match res {
241 Ok(_) => {
242 return Ok(circuit);
243 }
244 Err(e) => {
245 return Err(format!("Error while parsing:\n{}", e).to_string());
246 }
247 }
248}
249
250pub fn parse_blif_file(input_file_path: &str) -> Result<Vec<ParsedPrimitive>, String> {
251 let blif_file = fs::read_to_string(input_file_path);
252 match blif_file {
253 Ok(blif_str) => {
254 return parse_blif(&blif_str);
255 }
256 Err(e) => {
257 return Err(format!("Error while reading the file:\n{}", e).to_string());
258 }
259 }
260}
261
262#[cfg(test)]
263pub mod parser_tests {
264 use super::*;
265
266 pub fn test_blif_parser(file_path: &str) -> bool {
267 let res = parse_blif_file(&file_path);
268 match res {
269 Ok(_) => true,
270 Err(err) => {
271 println!("blif file parsing error:\n{}", err);
272 false
273 }
274 }
275 }
276
277 #[test]
278 pub fn test_adder_parse() {
279 assert_eq!(test_blif_parser("./tests/Adder.lut.blif"), true);
280 }
281
282 #[test]
283 pub fn test_gcd_parse() {
284 assert_eq!(test_blif_parser("./tests/GCD.lut.blif"), true);
285 }
286
287 #[test]
288 pub fn test_const_parse() {
289 assert_eq!(test_blif_parser("./tests/Const.lut.blif"), true);
290 }
291}