verilogParse.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. #
  2. # verilogParse.py
  3. #
  4. # an example of using the pyparsing module to be able to process Verilog files
  5. # uses BNF defined at http://www.verilog.com/VerilogBNF.html
  6. #
  7. # Copyright (c) 2004-2011 Paul T. McGuire. All rights reserved.
  8. #
  9. # Permission is hereby granted, free of charge, to any person obtaining
  10. # a copy of this software and associated documentation files (the
  11. # "Software"), to deal in the Software without restriction, including
  12. # without limitation the rights to use, copy, modify, merge, publish,
  13. # distribute, sublicense, and/or sell copies of the Software, and to
  14. # permit persons to whom the Software is furnished to do so, subject to
  15. # the following conditions:
  16. #
  17. # The above copyright notice and this permission notice shall be
  18. # included in all copies or substantial portions of the Software.
  19. #
  20. # If you find this software to be useful, please make a donation to one
  21. # of the following charities:
  22. # - the Red Cross (https://www.redcross.org/)
  23. # - Hospice Austin (https://www.hospiceaustin.org/)
  24. #
  25. # DISCLAIMER:
  26. # THIS SOFTWARE IS PROVIDED BY PAUL T. McGUIRE ``AS IS'' AND ANY EXPRESS OR
  27. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  28. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  29. # EVENT SHALL PAUL T. McGUIRE OR CO-CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  30. # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  31. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OFUSE,
  32. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  33. # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  34. # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  35. # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. #
  37. # For questions or inquiries regarding this license, or commercial use of
  38. # this software, contact the author via e-mail: ptmcg@users.sourceforge.net
  39. #
  40. # Todo:
  41. # - add pre-process pass to implement compilerDirectives (ifdef, include, etc.)
  42. #
  43. # Revision History:
  44. #
  45. # 1.0 - Initial release
  46. # 1.0.1 - Fixed grammar errors:
  47. # . real declaration was incorrect
  48. # . tolerant of '=>' for '*>' operator
  49. # . tolerant of '?' as hex character
  50. # . proper handling of mintypmax_expr within path delays
  51. # 1.0.2 - Performance tuning (requires pyparsing 1.3)
  52. # 1.0.3 - Performance updates, using Regex (requires pyparsing 1.4)
  53. # 1.0.4 - Performance updates, enable packrat parsing (requires pyparsing 1.4.2)
  54. # 1.0.5 - Converted keyword Literals to Keywords, added more use of Group to
  55. # group parsed results tokens
  56. # 1.0.6 - Added support for module header with no ports list (thanks, Thomas Dejanovic!)
  57. # 1.0.7 - Fixed erroneous '<<' Forward definition in timCheckCond, omitting ()'s
  58. # 1.0.8 - Re-released under MIT license
  59. # 1.0.9 - Enhanced udpInstance to handle identifiers with leading '\' and subscripting
  60. # 1.0.10 - Fixed change added in 1.0.9 to work for all identifiers, not just those used
  61. # for udpInstance.
  62. # 1.0.11 - Fixed bug in inst_args, content alternatives were reversed
  63. #
  64. import time
  65. import pprint
  66. import sys
  67. __version__ = "1.0.11"
  68. from pyparsing import Literal, Keyword, Word, OneOrMore, ZeroOrMore, \
  69. Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, \
  70. alphanums, dblQuotedString, empty, ParseException, oneOf, \
  71. StringEnd, FollowedBy, ParserElement, Regex, cppStyleComment
  72. import pyparsing
  73. usePackrat = False
  74. packratOn = False
  75. if usePackrat:
  76. try:
  77. ParserElement.enablePackrat()
  78. except Exception:
  79. pass
  80. else:
  81. packratOn = True
  82. def dumpTokens(s,l,t):
  83. import pprint
  84. pprint.pprint( t.asList() )
  85. verilogbnf = None
  86. def Verilog_BNF():
  87. global verilogbnf
  88. if verilogbnf is None:
  89. # compiler directives
  90. compilerDirective = Combine( "`" + \
  91. oneOf("define undef ifdef else endif default_nettype "
  92. "include resetall timescale unconnected_drive "
  93. "nounconnected_drive celldefine endcelldefine") + \
  94. restOfLine ).setName("compilerDirective")
  95. # primitives
  96. SEMI,COLON,LPAR,RPAR,LBRACE,RBRACE,LBRACK,RBRACK,DOT,COMMA,EQ = map(Literal,";:(){}[].,=")
  97. identLead = alphas+"$_"
  98. identBody = alphanums+"$_"
  99. identifier1 = Regex( r"\.?["+identLead+"]["+identBody+r"]*(\.["+identLead+"]["+identBody+"]*)*"
  100. ).setName("baseIdent")
  101. identifier2 = Regex(r"\\\S+").setParseAction(lambda t:t[0][1:]).setName("escapedIdent")#.setDebug()
  102. identifier = identifier1 | identifier2
  103. assert(identifier2 == r'\abc')
  104. hexnums = nums + "abcdefABCDEF" + "_?"
  105. base = Regex("'[bBoOdDhH]").setName("base")
  106. basedNumber = Combine( Optional( Word(nums + "_") ) + base + Word(hexnums+"xXzZ"),
  107. joinString=" ", adjacent=False ).setName("basedNumber")
  108. #~ number = ( basedNumber | Combine( Word( "+-"+spacedNums, spacedNums ) +
  109. #~ Optional( DOT + Optional( Word( spacedNums ) ) ) +
  110. #~ Optional( e + Word( "+-"+spacedNums, spacedNums ) ) ).setName("numeric") )
  111. number = ( basedNumber | \
  112. Regex(r"[+-]?[0-9_]+(\.[0-9_]*)?([Ee][+-]?[0-9_]+)?") \
  113. ).setName("numeric")
  114. #~ decnums = nums + "_"
  115. #~ octnums = "01234567" + "_"
  116. expr = Forward().setName("expr")
  117. concat = Group( LBRACE + delimitedList( expr ) + RBRACE )
  118. multiConcat = Group("{" + expr + concat + "}").setName("multiConcat")
  119. funcCall = Group(identifier + LPAR + Optional( delimitedList( expr ) ) + RPAR).setName("funcCall")
  120. subscrRef = Group(LBRACK + delimitedList( expr, COLON ) + RBRACK)
  121. subscrIdentifier = Group( identifier + Optional( subscrRef ) )
  122. #~ scalarConst = "0" | (( FollowedBy('1') + oneOf("1'b0 1'b1 1'bx 1'bX 1'B0 1'B1 1'Bx 1'BX 1") ))
  123. scalarConst = Regex("0|1('[Bb][01xX])?")
  124. mintypmaxExpr = Group( expr + COLON + expr + COLON + expr ).setName("mintypmax")
  125. primary = (
  126. number |
  127. (LPAR + mintypmaxExpr + RPAR ) |
  128. ( LPAR + Group(expr) + RPAR ).setName("nestedExpr") |
  129. multiConcat |
  130. concat |
  131. dblQuotedString |
  132. funcCall |
  133. subscrIdentifier
  134. )
  135. unop = oneOf( "+ - ! ~ & ~& | ^| ^ ~^" ).setName("unop")
  136. binop = oneOf( "+ - * / % == != === !== && "
  137. "|| < <= > >= & | ^ ^~ >> << ** <<< >>>" ).setName("binop")
  138. expr << (
  139. ( unop + expr ) | # must be first!
  140. ( primary + "?" + expr + COLON + expr ) |
  141. ( primary + Optional( binop + expr ) )
  142. )
  143. lvalue = subscrIdentifier | concat
  144. # keywords
  145. if_ = Keyword("if")
  146. else_ = Keyword("else")
  147. edge = Keyword("edge")
  148. posedge = Keyword("posedge")
  149. negedge = Keyword("negedge")
  150. specify = Keyword("specify")
  151. endspecify = Keyword("endspecify")
  152. fork = Keyword("fork")
  153. join = Keyword("join")
  154. begin = Keyword("begin")
  155. end = Keyword("end")
  156. default = Keyword("default")
  157. forever = Keyword("forever")
  158. repeat = Keyword("repeat")
  159. while_ = Keyword("while")
  160. for_ = Keyword("for")
  161. case = oneOf( "case casez casex" )
  162. endcase = Keyword("endcase")
  163. wait = Keyword("wait")
  164. disable = Keyword("disable")
  165. deassign = Keyword("deassign")
  166. force = Keyword("force")
  167. release = Keyword("release")
  168. assign = Keyword("assign")
  169. eventExpr = Forward()
  170. eventTerm = ( posedge + expr ) | ( negedge + expr ) | expr | ( LPAR + eventExpr + RPAR )
  171. eventExpr << (
  172. Group( delimitedList( eventTerm, Keyword("or") ) )
  173. )
  174. eventControl = Group( "@" + ( ( LPAR + eventExpr + RPAR ) | identifier | "*" ) ).setName("eventCtrl")
  175. delayArg = ( number |
  176. Word(alphanums+"$_") | #identifier |
  177. ( LPAR + Group( delimitedList( mintypmaxExpr | expr ) ) + RPAR )
  178. ).setName("delayArg")#.setDebug()
  179. delay = Group( "#" + delayArg ).setName("delay")#.setDebug()
  180. delayOrEventControl = delay | eventControl
  181. assgnmt = Group( lvalue + EQ + Optional( delayOrEventControl ) + expr ).setName( "assgnmt" )
  182. nbAssgnmt = Group(( lvalue + "<=" + Optional( delay ) + expr ) |
  183. ( lvalue + "<=" + Optional( eventControl ) + expr )).setName( "nbassgnmt" )
  184. range = LBRACK + expr + COLON + expr + RBRACK
  185. paramAssgnmt = Group( identifier + EQ + expr ).setName("paramAssgnmt")
  186. parameterDecl = Group( "parameter" + Optional( range ) + delimitedList( paramAssgnmt ) + SEMI).setName("paramDecl")
  187. inputDecl = Group( "input" + Optional( range ) + delimitedList( identifier ) + SEMI )
  188. outputDecl = Group( "output" + Optional( range ) + delimitedList( identifier ) + SEMI )
  189. inoutDecl = Group( "inout" + Optional( range ) + delimitedList( identifier ) + SEMI )
  190. regIdentifier = Group( identifier + Optional( LBRACK + expr + COLON + expr + RBRACK ) )
  191. regDecl = Group( "reg" + Optional("signed") + Optional( range ) + delimitedList( regIdentifier ) + SEMI ).setName("regDecl")
  192. timeDecl = Group( "time" + delimitedList( regIdentifier ) + SEMI )
  193. integerDecl = Group( "integer" + delimitedList( regIdentifier ) + SEMI )
  194. strength0 = oneOf("supply0 strong0 pull0 weak0 highz0")
  195. strength1 = oneOf("supply1 strong1 pull1 weak1 highz1")
  196. driveStrength = Group( LPAR + ( ( strength0 + COMMA + strength1 ) |
  197. ( strength1 + COMMA + strength0 ) ) + RPAR ).setName("driveStrength")
  198. nettype = oneOf("wire tri tri1 supply0 wand triand tri0 supply1 wor trior trireg")
  199. expandRange = Optional( oneOf("scalared vectored") ) + range
  200. realDecl = Group( "real" + delimitedList( identifier ) + SEMI )
  201. eventDecl = Group( "event" + delimitedList( identifier ) + SEMI )
  202. blockDecl = (
  203. parameterDecl |
  204. regDecl |
  205. integerDecl |
  206. realDecl |
  207. timeDecl |
  208. eventDecl
  209. )
  210. stmt = Forward().setName("stmt")#.setDebug()
  211. stmtOrNull = stmt | SEMI
  212. caseItem = ( delimitedList( expr ) + COLON + stmtOrNull ) | \
  213. ( default + Optional(":") + stmtOrNull )
  214. stmt << Group(
  215. ( begin + Group( ZeroOrMore( stmt ) ) + end ).setName("begin-end") |
  216. ( if_ + Group(LPAR + expr + RPAR) + stmtOrNull + Optional( else_ + stmtOrNull ) ).setName("if") |
  217. ( delayOrEventControl + stmtOrNull ) |
  218. ( case + LPAR + expr + RPAR + OneOrMore( caseItem ) + endcase ) |
  219. ( forever + stmt ) |
  220. ( repeat + LPAR + expr + RPAR + stmt ) |
  221. ( while_ + LPAR + expr + RPAR + stmt ) |
  222. ( for_ + LPAR + assgnmt + SEMI + Group( expr ) + SEMI + assgnmt + RPAR + stmt ) |
  223. ( fork + ZeroOrMore( stmt ) + join ) |
  224. ( fork + COLON + identifier + ZeroOrMore( blockDecl ) + ZeroOrMore( stmt ) + end ) |
  225. ( wait + LPAR + expr + RPAR + stmtOrNull ) |
  226. ( "->" + identifier + SEMI ) |
  227. ( disable + identifier + SEMI ) |
  228. ( assign + assgnmt + SEMI ) |
  229. ( deassign + lvalue + SEMI ) |
  230. ( force + assgnmt + SEMI ) |
  231. ( release + lvalue + SEMI ) |
  232. ( begin + COLON + identifier + ZeroOrMore( blockDecl ) + ZeroOrMore( stmt ) + end ).setName("begin:label-end") |
  233. # these *have* to go at the end of the list!!!
  234. ( assgnmt + SEMI ) |
  235. ( nbAssgnmt + SEMI ) |
  236. ( Combine( Optional("$") + identifier ) + Optional( LPAR + delimitedList(expr|empty) + RPAR ) + SEMI )
  237. ).setName("stmtBody")
  238. """
  239. x::=<blocking_assignment> ;
  240. x||= <non_blocking_assignment> ;
  241. x||= if ( <expression> ) <statement_or_null>
  242. x||= if ( <expression> ) <statement_or_null> else <statement_or_null>
  243. x||= case ( <expression> ) <case_item>+ endcase
  244. x||= casez ( <expression> ) <case_item>+ endcase
  245. x||= casex ( <expression> ) <case_item>+ endcase
  246. x||= forever <statement>
  247. x||= repeat ( <expression> ) <statement>
  248. x||= while ( <expression> ) <statement>
  249. x||= for ( <assignment> ; <expression> ; <assignment> ) <statement>
  250. x||= <delay_or_event_control> <statement_or_null>
  251. x||= wait ( <expression> ) <statement_or_null>
  252. x||= -> <name_of_event> ;
  253. x||= <seq_block>
  254. x||= <par_block>
  255. x||= <task_enable>
  256. x||= <system_task_enable>
  257. x||= disable <name_of_task> ;
  258. x||= disable <name_of_block> ;
  259. x||= assign <assignment> ;
  260. x||= deassign <lvalue> ;
  261. x||= force <assignment> ;
  262. x||= release <lvalue> ;
  263. """
  264. alwaysStmt = Group( "always" + Optional(eventControl) + stmt ).setName("alwaysStmt")
  265. initialStmt = Group( "initial" + stmt ).setName("initialStmt")
  266. chargeStrength = Group( LPAR + oneOf( "small medium large" ) + RPAR ).setName("chargeStrength")
  267. continuousAssign = Group(
  268. assign + Optional( driveStrength ) + Optional( delay ) + delimitedList( assgnmt ) + SEMI
  269. ).setName("continuousAssign")
  270. tfDecl = (
  271. parameterDecl |
  272. inputDecl |
  273. outputDecl |
  274. inoutDecl |
  275. regDecl |
  276. timeDecl |
  277. integerDecl |
  278. realDecl
  279. )
  280. functionDecl = Group(
  281. "function" + Optional( range | "integer" | "real" ) + identifier + SEMI +
  282. Group( OneOrMore( tfDecl ) ) +
  283. Group( ZeroOrMore( stmt ) ) +
  284. "endfunction"
  285. )
  286. inputOutput = oneOf("input output")
  287. netDecl1Arg = ( nettype +
  288. Optional( expandRange ) +
  289. Optional( delay ) +
  290. Group( delimitedList( ~inputOutput + identifier ) ) )
  291. netDecl2Arg = ( "trireg" +
  292. Optional( chargeStrength ) +
  293. Optional( expandRange ) +
  294. Optional( delay ) +
  295. Group( delimitedList( ~inputOutput + identifier ) ) )
  296. netDecl3Arg = ( nettype +
  297. Optional( driveStrength ) +
  298. Optional( expandRange ) +
  299. Optional( delay ) +
  300. Group( delimitedList( assgnmt ) ) )
  301. netDecl1 = Group(netDecl1Arg + SEMI).setName("netDecl1")
  302. netDecl2 = Group(netDecl2Arg + SEMI).setName("netDecl2")
  303. netDecl3 = Group(netDecl3Arg + SEMI).setName("netDecl3")
  304. gateType = oneOf("and nand or nor xor xnor buf bufif0 bufif1 "
  305. "not notif0 notif1 pulldown pullup nmos rnmos "
  306. "pmos rpmos cmos rcmos tran rtran tranif0 "
  307. "rtranif0 tranif1 rtranif1" )
  308. gateInstance = Optional( Group( identifier + Optional( range ) ) ) + \
  309. LPAR + Group( delimitedList( expr ) ) + RPAR
  310. gateDecl = Group( gateType +
  311. Optional( driveStrength ) +
  312. Optional( delay ) +
  313. delimitedList( gateInstance) +
  314. SEMI )
  315. udpInstance = Group( Group( identifier + Optional(range | subscrRef) ) +
  316. LPAR + Group( delimitedList( expr ) ) + RPAR )
  317. udpInstantiation = Group( identifier -
  318. Optional( driveStrength ) +
  319. Optional( delay ) +
  320. delimitedList( udpInstance ) +
  321. SEMI ).setName("udpInstantiation")
  322. parameterValueAssignment = Group( Literal("#") + LPAR + Group( delimitedList( expr ) ) + RPAR )
  323. namedPortConnection = Group( DOT + identifier + LPAR + expr + RPAR ).setName("namedPortConnection")#.setDebug()
  324. assert(r'.\abc (abc )' == namedPortConnection)
  325. modulePortConnection = expr | empty
  326. #~ moduleInstance = Group( Group ( identifier + Optional(range) ) +
  327. #~ ( delimitedList( modulePortConnection ) |
  328. #~ delimitedList( namedPortConnection ) ) )
  329. inst_args = Group( LPAR + (delimitedList( namedPortConnection ) |
  330. delimitedList( modulePortConnection )) + RPAR).setName("inst_args")
  331. moduleInstance = Group( Group ( identifier + Optional(range) ) + inst_args ).setName("moduleInstance")#.setDebug()
  332. moduleInstantiation = Group( identifier +
  333. Optional( parameterValueAssignment ) +
  334. delimitedList( moduleInstance ).setName("moduleInstanceList") +
  335. SEMI ).setName("moduleInstantiation")
  336. parameterOverride = Group( "defparam" + delimitedList( paramAssgnmt ) + SEMI )
  337. task = Group( "task" + identifier + SEMI +
  338. ZeroOrMore( tfDecl ) +
  339. stmtOrNull +
  340. "endtask" )
  341. specparamDecl = Group( "specparam" + delimitedList( paramAssgnmt ) + SEMI )
  342. pathDescr1 = Group( LPAR + subscrIdentifier + "=>" + subscrIdentifier + RPAR )
  343. pathDescr2 = Group( LPAR + Group( delimitedList( subscrIdentifier ) ) + "*>" +
  344. Group( delimitedList( subscrIdentifier ) ) + RPAR )
  345. pathDescr3 = Group( LPAR + Group( delimitedList( subscrIdentifier ) ) + "=>" +
  346. Group( delimitedList( subscrIdentifier ) ) + RPAR )
  347. pathDelayValue = Group( ( LPAR + Group( delimitedList( mintypmaxExpr | expr ) ) + RPAR ) |
  348. mintypmaxExpr |
  349. expr )
  350. pathDecl = Group( ( pathDescr1 | pathDescr2 | pathDescr3 ) + EQ + pathDelayValue + SEMI ).setName("pathDecl")
  351. portConditionExpr = Forward()
  352. portConditionTerm = Optional(unop) + subscrIdentifier
  353. portConditionExpr << portConditionTerm + Optional( binop + portConditionExpr )
  354. polarityOp = oneOf("+ -")
  355. levelSensitivePathDecl1 = Group(
  356. if_ + Group(LPAR + portConditionExpr + RPAR) +
  357. subscrIdentifier + Optional( polarityOp ) + "=>" + subscrIdentifier + EQ +
  358. pathDelayValue +
  359. SEMI )
  360. levelSensitivePathDecl2 = Group(
  361. if_ + Group(LPAR + portConditionExpr + RPAR) +
  362. LPAR + Group( delimitedList( subscrIdentifier ) ) + Optional( polarityOp ) + "*>" +
  363. Group( delimitedList( subscrIdentifier ) ) + RPAR + EQ +
  364. pathDelayValue +
  365. SEMI )
  366. levelSensitivePathDecl = levelSensitivePathDecl1 | levelSensitivePathDecl2
  367. edgeIdentifier = posedge | negedge
  368. edgeSensitivePathDecl1 = Group(
  369. Optional( if_ + Group(LPAR + expr + RPAR) ) +
  370. LPAR + Optional( edgeIdentifier ) +
  371. subscrIdentifier + "=>" +
  372. LPAR + subscrIdentifier + Optional( polarityOp ) + COLON + expr + RPAR + RPAR +
  373. EQ +
  374. pathDelayValue +
  375. SEMI )
  376. edgeSensitivePathDecl2 = Group(
  377. Optional( if_ + Group(LPAR + expr + RPAR) ) +
  378. LPAR + Optional( edgeIdentifier ) +
  379. subscrIdentifier + "*>" +
  380. LPAR + delimitedList( subscrIdentifier ) + Optional( polarityOp ) + COLON + expr + RPAR + RPAR +
  381. EQ +
  382. pathDelayValue +
  383. SEMI )
  384. edgeSensitivePathDecl = edgeSensitivePathDecl1 | edgeSensitivePathDecl2
  385. edgeDescr = oneOf("01 10 0x x1 1x x0").setName("edgeDescr")
  386. timCheckEventControl = Group( posedge | negedge | (edge + LBRACK + delimitedList( edgeDescr ) + RBRACK ))
  387. timCheckCond = Forward()
  388. timCondBinop = oneOf("== === != !==")
  389. timCheckCondTerm = ( expr + timCondBinop + scalarConst ) | ( Optional("~") + expr )
  390. timCheckCond << ( ( LPAR + timCheckCond + RPAR ) | timCheckCondTerm )
  391. timCheckEvent = Group( Optional( timCheckEventControl ) +
  392. subscrIdentifier +
  393. Optional( "&&&" + timCheckCond ) )
  394. timCheckLimit = expr
  395. controlledTimingCheckEvent = Group( timCheckEventControl + subscrIdentifier +
  396. Optional( "&&&" + timCheckCond ) )
  397. notifyRegister = identifier
  398. systemTimingCheck1 = Group( "$setup" +
  399. LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit +
  400. Optional( COMMA + notifyRegister ) + RPAR +
  401. SEMI )
  402. systemTimingCheck2 = Group( "$hold" +
  403. LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit +
  404. Optional( COMMA + notifyRegister ) + RPAR +
  405. SEMI )
  406. systemTimingCheck3 = Group( "$period" +
  407. LPAR + controlledTimingCheckEvent + COMMA + timCheckLimit +
  408. Optional( COMMA + notifyRegister ) + RPAR +
  409. SEMI )
  410. systemTimingCheck4 = Group( "$width" +
  411. LPAR + controlledTimingCheckEvent + COMMA + timCheckLimit +
  412. Optional( COMMA + expr + COMMA + notifyRegister ) + RPAR +
  413. SEMI )
  414. systemTimingCheck5 = Group( "$skew" +
  415. LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit +
  416. Optional( COMMA + notifyRegister ) + RPAR +
  417. SEMI )
  418. systemTimingCheck6 = Group( "$recovery" +
  419. LPAR + controlledTimingCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit +
  420. Optional( COMMA + notifyRegister ) + RPAR +
  421. SEMI )
  422. systemTimingCheck7 = Group( "$setuphold" +
  423. LPAR + timCheckEvent + COMMA + timCheckEvent + COMMA + timCheckLimit + COMMA + timCheckLimit +
  424. Optional( COMMA + notifyRegister ) + RPAR +
  425. SEMI )
  426. systemTimingCheck = (FollowedBy('$') + ( systemTimingCheck1 | systemTimingCheck2 | systemTimingCheck3 |
  427. systemTimingCheck4 | systemTimingCheck5 | systemTimingCheck6 | systemTimingCheck7 )).setName("systemTimingCheck")
  428. sdpd = if_ + Group(LPAR + expr + RPAR) + \
  429. ( pathDescr1 | pathDescr2 ) + EQ + pathDelayValue + SEMI
  430. specifyItem = ~Keyword("endspecify") +(
  431. specparamDecl |
  432. pathDecl |
  433. levelSensitivePathDecl |
  434. edgeSensitivePathDecl |
  435. systemTimingCheck |
  436. sdpd
  437. )
  438. """
  439. x::= <specparam_declaration>
  440. x||= <path_declaration>
  441. x||= <level_sensitive_path_declaration>
  442. x||= <edge_sensitive_path_declaration>
  443. x||= <system_timing_check>
  444. x||= <sdpd>
  445. """
  446. specifyBlock = Group( "specify" + ZeroOrMore( specifyItem ) + "endspecify" ).setName("specifyBlock")
  447. moduleItem = ~Keyword("endmodule") + (
  448. parameterDecl |
  449. inputDecl |
  450. outputDecl |
  451. inoutDecl |
  452. regDecl |
  453. netDecl3 |
  454. netDecl1 |
  455. netDecl2 |
  456. timeDecl |
  457. integerDecl |
  458. realDecl |
  459. eventDecl |
  460. gateDecl |
  461. parameterOverride |
  462. continuousAssign |
  463. specifyBlock |
  464. initialStmt |
  465. alwaysStmt |
  466. task |
  467. functionDecl |
  468. # these have to be at the end - they start with identifiers
  469. moduleInstantiation |
  470. udpInstantiation
  471. )
  472. """ All possible moduleItems, from Verilog grammar spec
  473. x::= <parameter_declaration>
  474. x||= <input_declaration>
  475. x||= <output_declaration>
  476. x||= <inout_declaration>
  477. ?||= <net_declaration> (spec does not seem consistent for this item)
  478. x||= <reg_declaration>
  479. x||= <time_declaration>
  480. x||= <integer_declaration>
  481. x||= <real_declaration>
  482. x||= <event_declaration>
  483. x||= <gate_declaration>
  484. x||= <UDP_instantiation>
  485. x||= <module_instantiation>
  486. x||= <parameter_override>
  487. x||= <continuous_assign>
  488. x||= <specify_block>
  489. x||= <initial_statement>
  490. x||= <always_statement>
  491. x||= <task>
  492. x||= <function>
  493. """
  494. portRef = subscrIdentifier
  495. portExpr = portRef | Group( LBRACE + delimitedList( portRef ) + RBRACE )
  496. port = portExpr | Group( ( DOT + identifier + LPAR + portExpr + RPAR ) )
  497. moduleHdr = Group ( oneOf("module macromodule") + identifier +
  498. Optional( LPAR + Group( Optional( delimitedList(
  499. Group(oneOf("input output") +
  500. (netDecl1Arg | netDecl2Arg | netDecl3Arg) ) |
  501. port ) ) ) +
  502. RPAR ) + SEMI ).setName("moduleHdr")
  503. module = Group( moduleHdr +
  504. Group( ZeroOrMore( moduleItem ) ) +
  505. "endmodule" ).setName("module")#.setDebug()
  506. udpDecl = outputDecl | inputDecl | regDecl
  507. #~ udpInitVal = oneOf("1'b0 1'b1 1'bx 1'bX 1'B0 1'B1 1'Bx 1'BX 1 0 x X")
  508. udpInitVal = (Regex("1'[bB][01xX]") | Regex("[01xX]")).setName("udpInitVal")
  509. udpInitialStmt = Group( "initial" +
  510. identifier + EQ + udpInitVal + SEMI ).setName("udpInitialStmt")
  511. levelSymbol = oneOf("0 1 x X ? b B")
  512. levelInputList = Group( OneOrMore( levelSymbol ).setName("levelInpList") )
  513. outputSymbol = oneOf("0 1 x X")
  514. combEntry = Group( levelInputList + COLON + outputSymbol + SEMI )
  515. edgeSymbol = oneOf("r R f F p P n N *")
  516. edge = Group( LPAR + levelSymbol + levelSymbol + RPAR ) | \
  517. Group( edgeSymbol )
  518. edgeInputList = Group( ZeroOrMore( levelSymbol ) + edge + ZeroOrMore( levelSymbol ) )
  519. inputList = levelInputList | edgeInputList
  520. seqEntry = Group( inputList + COLON + levelSymbol + COLON + ( outputSymbol | "-" ) + SEMI ).setName("seqEntry")
  521. udpTableDefn = Group( "table" +
  522. OneOrMore( combEntry | seqEntry ) +
  523. "endtable" ).setName("table")
  524. """
  525. <UDP>
  526. ::= primitive <name_of_UDP> ( <name_of_variable> <,<name_of_variable>>* ) ;
  527. <UDP_declaration>+
  528. <UDP_initial_statement>?
  529. <table_definition>
  530. endprimitive
  531. """
  532. udp = Group( "primitive" + identifier +
  533. LPAR + Group( delimitedList( identifier ) ) + RPAR + SEMI +
  534. OneOrMore( udpDecl ) +
  535. Optional( udpInitialStmt ) +
  536. udpTableDefn +
  537. "endprimitive" )
  538. verilogbnf = OneOrMore( module | udp ) + StringEnd()
  539. verilogbnf.ignore( cppStyleComment )
  540. verilogbnf.ignore( compilerDirective )
  541. return verilogbnf
  542. def test( strng ):
  543. tokens = []
  544. try:
  545. tokens = Verilog_BNF().parseString( strng )
  546. except ParseException as err:
  547. print(err.line)
  548. print(" "*(err.column-1) + "^")
  549. print(err)
  550. return tokens
  551. #~ if __name__ == "__main__":
  552. if 0:
  553. import pprint
  554. toptest = """
  555. module TOP( in, out );
  556. input [7:0] in;
  557. output [5:0] out;
  558. COUNT_BITS8 count_bits( .IN( in ), .C( out ) );
  559. endmodule"""
  560. pprint.pprint( test(toptest).asList() )
  561. else:
  562. def main():
  563. print("Verilog parser test (V %s)" % __version__)
  564. print(" - using pyparsing version", pyparsing.__version__)
  565. print(" - using Python version", sys.version)
  566. if packratOn: print(" - using packrat parsing")
  567. print()
  568. import os
  569. import gc
  570. failCount = 0
  571. Verilog_BNF()
  572. numlines = 0
  573. startTime = time.clock()
  574. fileDir = "verilog"
  575. #~ fileDir = "verilog/new"
  576. #~ fileDir = "verilog/new2"
  577. #~ fileDir = "verilog/new3"
  578. allFiles = [f for f in os.listdir(fileDir) if f.endswith(".v")]
  579. #~ allFiles = [ "list_path_delays_test.v" ]
  580. #~ allFiles = [ "escapedIdent.v" ]
  581. #~ allFiles = filter( lambda f : f.startswith("a") and f.endswith(".v"), os.listdir(fileDir) )
  582. #~ allFiles = filter( lambda f : f.startswith("c") and f.endswith(".v"), os.listdir(fileDir) )
  583. #~ allFiles = [ "ff.v" ]
  584. pp = pprint.PrettyPrinter( indent=2 )
  585. totalTime = 0
  586. for vfile in allFiles:
  587. gc.collect()
  588. fnam = fileDir + "/"+vfile
  589. infile = open(fnam)
  590. filelines = infile.readlines()
  591. infile.close()
  592. print(fnam, len(filelines), end=' ')
  593. numlines += len(filelines)
  594. teststr = "".join(filelines)
  595. time1 = time.clock()
  596. tokens = test( teststr )
  597. time2 = time.clock()
  598. elapsed = time2-time1
  599. totalTime += elapsed
  600. if ( len( tokens ) ):
  601. print("OK", elapsed)
  602. #~ print "tokens="
  603. #~ pp.pprint( tokens.asList() )
  604. #~ print
  605. ofnam = fileDir + "/parseOutput/" + vfile + ".parsed.txt"
  606. outfile = open(ofnam,"w")
  607. outfile.write( teststr )
  608. outfile.write("\n")
  609. outfile.write("\n")
  610. outfile.write(pp.pformat(tokens.asList()))
  611. outfile.write("\n")
  612. outfile.close()
  613. else:
  614. print("failed", elapsed)
  615. failCount += 1
  616. for i,line in enumerate(filelines,1):
  617. print("%4d: %s" % (i,line.rstrip()))
  618. endTime = time.clock()
  619. print("Total parse time:", totalTime)
  620. print("Total source lines:", numlines)
  621. print("Average lines/sec:", ( "%.1f" % (float(numlines)/(totalTime+.05 ) ) ))
  622. if failCount:
  623. print("FAIL - %d files failed to parse" % failCount)
  624. else:
  625. print("SUCCESS - all files parsed")
  626. return 0
  627. #~ from line_profiler import LineProfiler
  628. #~ from pyparsing import ParseResults
  629. #~ lp = LineProfiler(ParseResults.__init__)
  630. main()
  631. #~ lp.print_stats()
  632. #~ import hotshot
  633. #~ p = hotshot.Profile("vparse.prof",1,1)
  634. #~ p.start()
  635. #~ main()
  636. #~ p.stop()
  637. #~ p.close()