260 lines
8.6 KiB
Plaintext
260 lines
8.6 KiB
Plaintext
/* C++ parsers require Bison 3 */
|
|
%require "3.0"
|
|
%language "C++"
|
|
|
|
/* Write-out tokens header file */
|
|
%defines
|
|
|
|
/* Use Bison's 'variant' to store values.
|
|
* This allows us to use non POD types (e.g.
|
|
* with constructors/destrictors), which is
|
|
* not possible with the default mode which
|
|
* uses unions.
|
|
*/
|
|
%define api.value.type variant
|
|
|
|
/*
|
|
* Use the 'complete' symbol type (i.e. variant)
|
|
* in the lexer
|
|
*/
|
|
%define api.token.constructor
|
|
|
|
/*
|
|
* Add a prefix the make_* functions used to
|
|
* create the symbols
|
|
*/
|
|
%define api.token.prefix {TOKEN_}
|
|
|
|
/*
|
|
* Use a re-entrant (no global vars) parser
|
|
*/
|
|
/*%define api.pure full*/
|
|
|
|
/* Wrap everything in our namespace */
|
|
%define api.namespace {blifparse}
|
|
|
|
/* Name the parser class */
|
|
%define parser_class_name {Parser}
|
|
|
|
/* Match the flex prefix */
|
|
%define api.prefix {blifparse_}
|
|
|
|
/* Extra checks for correct usage */
|
|
%define parse.assert
|
|
|
|
/* Enable debugging info */
|
|
%define parse.trace
|
|
|
|
/* Better error reporting */
|
|
%define parse.error verbose
|
|
|
|
/*
|
|
* Fixes inaccuracy in verbose error reporting.
|
|
* May be slow for some grammars.
|
|
*/
|
|
/*%define parse.lac full*/
|
|
|
|
/* Track locations */
|
|
/*%locations*/
|
|
|
|
/* Generate a table of token names */
|
|
%token-table
|
|
|
|
%lex-param {Lexer& lexer}
|
|
%parse-param {Lexer& lexer}
|
|
%parse-param {Callback& callback}
|
|
|
|
|
|
%code requires {
|
|
#include <memory>
|
|
#include "blifparse.hpp"
|
|
#include "blif_lexer_fwd.hpp"
|
|
}
|
|
|
|
%code top {
|
|
#include "blif_lexer.hpp"
|
|
//Bison calls blifparse_lex() to get the next token.
|
|
//We use the Lexer class as the interface to the lexer, so we
|
|
//re-defined the function to tell Bison how to get the next token.
|
|
static blifparse::Parser::symbol_type blifparse_lex(blifparse::Lexer& lexer) {
|
|
return lexer.next_token();
|
|
}
|
|
}
|
|
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
#include "assert.h"
|
|
|
|
#include "blifparse.hpp"
|
|
#include "blif_common.hpp"
|
|
#include "blif_error.hpp"
|
|
|
|
using namespace blifparse;
|
|
|
|
%}
|
|
|
|
/* Declare constant */
|
|
%token DOT_NAMES ".names"
|
|
%token DOT_LATCH ".latch"
|
|
%token DOT_MODEL ".model"
|
|
%token DOT_SUBCKT ".subckt"
|
|
%token DOT_INPUTS ".inputs"
|
|
%token DOT_OUTPUTS ".outputs"
|
|
%token DOT_CLOCK ".clock"
|
|
%token DOT_END ".end"
|
|
%token DOT_BLACKBOX ".blackbox"
|
|
%token LATCH_FE "fe"
|
|
%token LATCH_RE "re"
|
|
%token LATCH_AH "ah"
|
|
%token LATCH_AL "al"
|
|
%token LATCH_AS "as"
|
|
%token NIL "NIL"
|
|
%token LATCH_INIT_2 "2"
|
|
%token LATCH_INIT_3 "3"
|
|
%token LOGIC_FALSE "0"
|
|
%token LOGIC_TRUE "1"
|
|
%token LOGIC_DONT_CARE "-"
|
|
%token EQ "="
|
|
%token EOL "end-of-line"
|
|
%token EOF 0 "end-of-file"
|
|
|
|
/*BLIF extensions */
|
|
%token DOT_CONN ".conn"
|
|
%token DOT_ATTR ".attr"
|
|
%token DOT_PARAM ".param"
|
|
%token DOT_CNAME ".cname"
|
|
|
|
/* declare variable tokens */
|
|
%token <std::string> STRING
|
|
|
|
/* declare types */
|
|
%type <SubCkt> subckt
|
|
%type <Names> names
|
|
%type <std::vector<std::string>> string_list
|
|
%type <std::vector<LogicValue>> so_cover_row
|
|
%type <LogicValue> logic_value
|
|
%type <LogicValue> latch_init
|
|
%type <std::string> latch_control
|
|
%type <LatchType> latch_type
|
|
|
|
/* BLIF Extensions */
|
|
%type <Conn> conn
|
|
%type <Cname> cname
|
|
%type <Attr> attr
|
|
%type <Param> param
|
|
|
|
/* Top level rule */
|
|
%start blif_data
|
|
|
|
%%
|
|
|
|
blif_data: /*empty*/ { }
|
|
| blif_data DOT_MODEL STRING EOL { callback.lineno(lexer.lineno()-1); callback.begin_model($3); }
|
|
| blif_data DOT_INPUTS string_list EOL { callback.lineno(lexer.lineno()-1); callback.inputs($3); }
|
|
| blif_data DOT_OUTPUTS string_list EOL { callback.lineno(lexer.lineno()-1); callback.outputs($3); }
|
|
| blif_data names { callback.lineno(lexer.lineno()-1); callback.names($2.nets, $2.so_cover); }
|
|
| blif_data subckt EOL {
|
|
if($2.ports.size() != $2.nets.size()) {
|
|
blif_error_wrap(callback ,lexer.lineno()-1, lexer.text(),
|
|
"Mismatched subckt port and net connection(s) size do not match"
|
|
" (%zu ports, %zu nets)", $2.ports.size(), $2.nets.size());
|
|
}
|
|
callback.lineno(lexer.lineno()-1);
|
|
callback.subckt($2.model, $2.ports, $2.nets);
|
|
}
|
|
| blif_data latch EOL { /*callback already called */ }
|
|
| blif_data DOT_BLACKBOX EOL { callback.lineno(lexer.lineno()-1); callback.blackbox(); }
|
|
| blif_data DOT_END EOL { callback.lineno(lexer.lineno()-1); callback.end_model(); }
|
|
| blif_data conn EOL { callback.lineno(lexer.lineno()-1); callback.conn($2.src, $2.dst); }
|
|
| blif_data cname EOL { callback.lineno(lexer.lineno()-1); callback.cname($2.name); }
|
|
| blif_data attr EOL { callback.lineno(lexer.lineno()-1); callback.attr($2.name, $2.value); }
|
|
| blif_data param EOL { callback.lineno(lexer.lineno()-1); callback.param($2.name, $2.value); }
|
|
| blif_data EOL { /* eat end-of-lines */}
|
|
;
|
|
|
|
names: DOT_NAMES string_list EOL { $$ = Names(); $$.nets = $2; }
|
|
| names so_cover_row EOL {
|
|
$$ = std::move($1);
|
|
if($$.nets.size() != $2.size()) {
|
|
blif_error_wrap(callback, lexer.lineno()-1, lexer.text(),
|
|
"Mismatched .names single-output cover row."
|
|
" names connected to %zu net(s), but cover row has %zu element(s)",
|
|
$$.nets.size(), $2.size());
|
|
}
|
|
$$.so_cover.push_back($2);
|
|
}
|
|
;
|
|
|
|
subckt: DOT_SUBCKT STRING { $$ = SubCkt(); $$.model = $2; }
|
|
| subckt STRING EQ STRING { $$ = std::move($1); $$.ports.push_back($2); $$.nets.push_back($4); }
|
|
;
|
|
|
|
latch: DOT_LATCH STRING STRING {
|
|
//Input and output only
|
|
callback.lineno(lexer.lineno());
|
|
callback.latch($2, $3, LatchType::UNSPECIFIED, "", LogicValue::UNKOWN);
|
|
}
|
|
| DOT_LATCH STRING STRING latch_type latch_control {
|
|
//Input, output, type and control
|
|
callback.lineno(lexer.lineno());
|
|
callback.latch($2, $3, $4, $5, LogicValue::UNKOWN);
|
|
}
|
|
| DOT_LATCH STRING STRING latch_type latch_control latch_init {
|
|
//Input, output, type, control and init-value
|
|
callback.lineno(lexer.lineno());
|
|
callback.latch($2, $3, $4, $5, $6);
|
|
}
|
|
| DOT_LATCH STRING STRING latch_init {
|
|
//Input, output, and init-value
|
|
callback.lineno(lexer.lineno());
|
|
callback.latch($2, $3, LatchType::UNSPECIFIED, "", $4);
|
|
}
|
|
;
|
|
|
|
latch_init: LOGIC_TRUE { $$ = LogicValue::TRUE; }
|
|
| LOGIC_FALSE { $$ = LogicValue::FALSE; }
|
|
| LATCH_INIT_2 { $$ = LogicValue::DONT_CARE; }
|
|
| LATCH_INIT_3 { $$ = LogicValue::UNKOWN; }
|
|
;
|
|
|
|
latch_control: STRING { $$ = $1;}
|
|
| NIL { $$ = ""; }
|
|
;
|
|
|
|
latch_type: LATCH_FE { $$ = LatchType::FALLING_EDGE; }
|
|
| LATCH_RE { $$ = LatchType::RISING_EDGE; }
|
|
| LATCH_AH { $$ = LatchType::ACTIVE_HIGH; }
|
|
| LATCH_AL { $$ = LatchType::ACTIVE_LOW; }
|
|
| LATCH_AS { $$ = LatchType::ASYNCHRONOUS; }
|
|
;
|
|
|
|
so_cover_row: logic_value { $$ = std::vector<LogicValue>(); $$.push_back($1); }
|
|
| so_cover_row logic_value { $$ = std::move($1); $$.push_back($2); }
|
|
;
|
|
|
|
logic_value: LOGIC_TRUE { $$ = LogicValue::TRUE; }
|
|
| LOGIC_FALSE { $$ = LogicValue::FALSE; }
|
|
| LOGIC_DONT_CARE { $$ = LogicValue::DONT_CARE; }
|
|
;
|
|
|
|
string_list: /*empty*/ { $$ = std::vector<std::string>(); }
|
|
| string_list STRING { $$ = std::move($1); $$.push_back($2); }
|
|
;
|
|
|
|
/*
|
|
* BLIF Extensions
|
|
*/
|
|
conn: DOT_CONN STRING STRING { $$ = Conn(); $$.src = $2; $$.dst = $3; }
|
|
cname: DOT_CNAME STRING { $$ = Cname(); $$.name = $2; }
|
|
attr: DOT_ATTR STRING STRING { $$ = Attr(); $$.name = $2; $$.value = $3; }
|
|
| DOT_ATTR STRING { $$ = Attr(); $$.name = $2; $$.value = ""; }
|
|
param: DOT_PARAM STRING STRING { $$ = Param(); $$.name = $2; $$.value = $3; }
|
|
| DOT_PARAM STRING { $$ = Param(); $$.name = $2; $$.value = ""; }
|
|
|
|
%%
|
|
|
|
void blifparse::Parser::error(const std::string& msg) {
|
|
blif_error_wrap(callback, lexer.lineno(), lexer.text(), msg.c_str());
|
|
}
|