# Required classess to pass in bindings: # * Comment # * LogicLine # * LogicGate # Doesn't handle Line Continuations with \ at the end of the line currently, # see bliffy.parser.remove_continuations and pass the result to the grammar # for now #nonws = <(~non_string anything)+>:nws -> nws nonws = <(~(' ' | '\t' | '\r\n' | '\r' | '\n' | '#') anything)+>:nws -> nws # XXX: ugly, I'm not really sure what's allowed in blif strings (probably anything except for whitespace, but that's slow to match with parsley) #nonws = <(letterOrDigit | '$' | '\\' | '[' | ']' | '_' | ':' | '.')+>:nws -> nws nonws_opt = <(~non_string anything)*>:nwso -> nwso #nonws_eq = <(~non_neq anything)+>:ret -> ret nonws_eq = <(~(' ' | '\t' | '\r\n' | '\r' | '\n' | '#' | '=') anything)*>:nwso -> nwso hspace = ' ' | '\t' vspace = '\r\n' | '\r' | '\n' single_ws = ' ' | '\t' | '\r\n' | '\r' | '\n' non_string = ' ' | '\t' | '\r\n' | '\r' | '\n' | '#' non_neq = ' ' | '\t' | '\r\n' | '\r' | '\n' | '#' | '=' comment = <'#' (~vspace anything)*>:ctext -> Comment(ctext) comment_line = comment:cmt vspace* -> cmt model_line = ".model" hspace+ :name hspace* comment?:comment vspace* -> ModelLine(name, comment) inputs_line = ".inputs" (hspace+ )+:inputs hspace* comment?:comment vspace* -> InputsLine(inputs, comment) outputs_line = ".outputs" (hspace+ )+:outputs hspace* comment?:comment vspace* -> OutputsLine(outputs, comment) clock_line = ".clock" (hspace+ )+:clocks hspace* comment?:comment vspace* -> ClockLine(clocks, comment) end_line = ".end" hspace* comment?:comment vspace* -> EndLine(comment) names_line = ".names" (hspace+ nonws)+:namelist hspace* comment?:comment vspace* -> NamesLine(namelist[:-1], namelist[-1], comment) pla_actual_digit = ('1' | '0'):char -> int(char) pla_digit_in = pla_actual_digit | '-' pla_line_single = pla_actual_digit:out_bit hspace* comment?:comment vspace* -> LogicLineSingle(out_bit, comment) pla_line_mult = pla_digit_in+:in_bits hspace+ pla_actual_digit:out_bit hspace* comment?:comment vspace* -> LogicLineMult(in_bits, out_bit, comment) pla_line = pla_line_mult | pla_line_single inner_pla_line = pla_line | comment_line logic_gate_block = names_line:nline inner_pla_line*:plas -> LogicGate(nline, plas) exdc_line = ".exdc" hspace* comment?:comment vspace* -> ExdcLine(comment) external_dont_care_block = exdc_line:exdcl comment_line*:comments names_line:nline inner_pla_line*:plas -> ExternalDontCare(nline, plas, exdcl, comments) latch_type = ("fe" | "re" | "ah" | "al" | "as"):type -> type latch_tcontrol = latch_type:type hspace+ nonws:control -> (type, control) latch_init_val = ('0' | '1' | '2' | '3'):char -> int(char) latch_line = ".latch" hspace+ nonws:input hspace+ nonws:output hspace* latch_tcontrol?:tcontrol hspace* latch_init_val?:init_val hspace* comment?:comment vspace* -> Latch.from_parsley(input, output, tcontrol, init_val, comment) # TODO: it might make sense to use nonws_opt:right here if blank values are allowed ("I4=" fex. currently fails # but should work with nonws_opt) formal_pair = nonws_eq:left '=' nonws:right -> (left, right) # XXX/TODO: are gates with no formal-actual-list valid? lib_gate_line = ".gate" hspace+ nonws:name (hspace+ formal_pair)*:pairs hspace* comment?:comment vspace* -> GateLine(name, pairs, comment) lib_mlatch_line = ".mlatch" hspace+ nonws:name (hspace+ formal_pair)*:pairs hspace+ nonws:control hspace* latch_init_val?:init_val hspace* comment?:comment vspace* -> MLatchLine(name, pairs, control, init_val, comment) # XXX: .attr and .param don't seem to be in the BLIF standard, probably specialized commands # Defining them anyway as they're pretty much needed for the IceStorm workflow/aranche-pnr/yosys yosys_bv_zero = ('0' | 'x' | 'X') -> '0' yosys_bv = (yosys_bv_zero | '1')+:bv -> ("bitvector", intbv("".join(bv))) yosys_strend = vspace | '"' yosys_esc_str = '"' <(~yosys_strend anything)+>:ret '"' -> ("quoted", ret) yosys_str_or_bv = yosys_bv | yosys_esc_str yosys_attr_line = ".attr" hspace+ nonws:name hspace+ yosys_str_or_bv:valtup hspace* comment?:comment vspace* -> (".attr", name, YosysPAValue(valtup[0], valtup[1], comment)) yosys_param_line = ".param" hspace+ nonws:name hspace+ yosys_str_or_bv:valtup hspace* comment?:comment vspace* -> (".param", name, YosysPAValue(valtup[0], valtup[1], comment)) # TODO: other yosys-specific bits are mentioned in http://www.clifford.at/yosys/cmd_write_blif.html , currently # (as of 2016-10-12) http://www.clifford.at/yosys/cmd_synth_ice40.html only uses -gates -attr -param so it's just # .attr and .param that are non-standard in the generated blif # (there's also .cname , might as well add that as well standard_lib_gate = lib_gate_line:libgate -> LibraryGate.from_parsley(libgate, [], type_="standard") # TODO: I need to handle .cname and comment lines in elines and in LibraryGate yosys_lib_gate = lib_gate_line:libgate (yosys_attr_line | yosys_param_line)*:elines -> LibraryGate.from_parsley(libgate, elines, type_="yosys") # TODO: the rest of the standard commands: .subckt, .search, the FSM commands, Clock Constraints, Delay Constraints standard_command = logic_gate_block | external_dont_care_block | latch_line | lib_mlatch_line | standard_lib_gate yosys_command = logic_gate_block | external_dont_care_block | latch_line | lib_mlatch_line | yosys_lib_gate # TODO: don't use names_line, use the LogicGate or similar blocks standard_any_line = standard_command | model_line | inputs_line | outputs_line | clock_line | end_line | comment_line yosys_any_line = yosys_command | model_line | inputs_line | outputs_line | clock_line | end_line | comment_line standard_every_line = (standard_any_line*):lines -> lines yosys_every_line = (yosys_any_line*):lines -> lines