@ -8,7 +8,7 @@ from collections import namedtuple
@@ -8,7 +8,7 @@ from collections import namedtuple
from lark import Lark , Transformer
from . import readtext
from . import log , readtext
from . circuit import Circuit , Node , Line
from . techlib import TechLib
@ -17,27 +17,21 @@ Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
@@ -17,27 +17,21 @@ Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
class SignalDeclaration :
def __init__ ( self , kind , tokens ) :
def __init__ ( self , kind , name , rnge = None ) :
self . left = None
self . right = None
self . kind = kind
if len ( tokens . children ) == 1 :
self . basename = tokens . children [ 0 ]
else :
self . basename = tokens . children [ 2 ]
self . left = int ( tokens . children [ 0 ] . value )
self . right = int ( tokens . children [ 1 ] . value )
self . basename = name
self . rnge = rnge
@property
def names ( self ) :
if self . left is None :
if self . rnge is None :
return [ self . basename ]
if self . left < = self . right :
return [ f ' { self . basename } [ { i } ] ' for i in range ( self . left , self . right + 1 ) ]
return [ f ' { self . basename } [ { i } ] ' for i in range ( self . left , self . right - 1 , - 1 ) ]
return [ f ' { self . basename } [ { i } ] ' for i in self . rnge ]
def __repr__ ( self ) :
return f " { self . kind } : { self . basename } [ { self . left } : { self . right } ] "
return f " { self . kind } : { self . basename } [ { self . rnge } ] "
class VerilogTransformer ( Transformer ) :
@ -57,28 +51,33 @@ class VerilogTransformer(Transformer):
@@ -57,28 +51,33 @@ class VerilogTransformer(Transformer):
@staticmethod
def instantiation ( args ) :
return Instantiation ( args [ 0 ] , args [ 1 ] ,
dict ( ( pin . children [ 0 ] , pin . children [ 1 ] ) for pin in args [ 2 : ] ) )
def input ( self , args ) :
for sd in [ SignalDeclaration ( ' input ' , signal ) for signal in args ] :
self . _signal_declarations [ sd . basename ] = sd
def inout ( self , args ) :
for sd in [ SignalDeclaration ( ' input ' , signal ) for signal in args ] : # just treat as input
dict ( ( pin . children [ 0 ] ,
pin . children [ 1 ] ) for pin in args [ 2 : ] if len ( pin . children ) > 1 ) )
def range ( self , args ) :
left = int ( args [ 0 ] . value )
right = int ( args [ 1 ] . value )
return range ( left , right + 1 ) if left < = right else range ( left , right - 1 , - 1 )
def declaration ( self , kind , args ) :
rnge = None
if isinstance ( args [ 0 ] , range ) :
rnge = args [ 0 ]
args = args [ 1 : ]
for sd in [ SignalDeclaration ( kind , signal , rnge ) for signal in args ] :
if kind != ' wire ' or sd . basename not in self . _signal_declarations :
self . _signal_declarations [ sd . basename ] = sd
def output ( self , args ) :
for sd in [ SignalDeclaration ( ' output ' , signal ) for signal in args ] :
self . _signal_declarations [ sd . basename ] = sd
def wire ( self , args ) :
for sd in [ SignalDeclaration ( ' wire ' , signal ) for signal in args ] :
self . _signal_declarations [ sd . basename ] = sd
def input ( self , args ) : self . declaration ( " input " , args )
def output ( self , args ) : self . declaration ( " output " , args )
def inout ( self , args ) : self . declaration ( " input " , args ) # just treat as input
def wire ( self , args ) : self . declaration ( " wire " , args )
def module ( self , args ) :
c = Circuit ( args [ 0 ] )
positions = { }
pos = 0
const_count = 0
for intf_sig in args [ 1 ] . children :
for name in self . _signal_declarations [ intf_sig ] . names :
positions [ name ] = pos
@ -107,15 +106,24 @@ class VerilogTransformer(Transformer):
@@ -107,15 +106,24 @@ class VerilogTransformer(Transformer):
elif s2 in c . forks :
assert s1 not in c . forks , ' assignment between two driven signals '
Line ( c , c . forks [ s2 ] , Node ( c , s1 ) )
elif s2 . startswith ( " 1 ' b " ) :
cnode = Node ( c , f ' __const { s2 [ 3 ] } _ { const_count } __ ' , f ' __const { s2 [ 3 ] } __ ' )
const_count + = 1
Line ( c , cnode , Node ( c , s1 ) )
for stmt in args [ 2 : ] : # pass 2: connect signals to readers
if isinstance ( stmt , Instantiation ) :
for p , s in stmt . pins . items ( ) :
n = c . cells [ stmt . name ]
if self . tlib . pin_is_output ( n . kind , p ) : continue
if s . startswith ( " 1 ' b " ) :
const = f ' __const { s [ 3 ] } __ '
if const not in c . cells :
Line ( c , Node ( c , const , const ) , Node ( c , s ) )
cname = f ' __const { s [ 3 ] } _ { const_count } __ '
cnode = Node ( c , cname , f ' __const { s [ 3 ] } __ ' )
const_count + = 1
s = cname
Line ( c , cnode , Node ( c , s ) )
if s not in c . forks :
log . warn ( f ' Signal not driven: { s } ' )
Node ( c , s ) # generate fork here
fork = c . forks [ s ]
if self . branchforks :
branchfork = Node ( c , fork . name + " ~ " + n . name + " / " + p )
@ -125,6 +133,9 @@ class VerilogTransformer(Transformer):
@@ -125,6 +133,9 @@ class VerilogTransformer(Transformer):
for sd in self . _signal_declarations . values ( ) :
if sd . kind == ' output ' :
for name in sd . names :
if name not in c . forks :
log . warn ( f ' Output not driven: { name } ' )
else :
Line ( c , c . forks [ name ] , c . cells [ name ] )
return c
@ -135,18 +146,19 @@ class VerilogTransformer(Transformer):
@@ -135,18 +146,19 @@ class VerilogTransformer(Transformer):
GRAMMAR = """
start : ( module ) *
module : " module " name parameters " ; " ( _statement ) * " endmodule "
parameters : " ( " [ name ( " , " name ) * ] " ) "
parameters : " ( " [ _namelist ] " ) "
_statement : input | output | inout | tri | wire | assign | instantiation
input : " input " signal ( " , " signal ) * " ; "
output : " output " signal ( " , " signal ) * " ; "
inout : " inout " signal ( " , " signal ) * " ; "
tri : " tri " name " ; "
wire : " wire " signal ( " , " signal ) * " ; "
input : " input " range ? _namelist " ; "
output : " output " range ? _namelist " ; "
inout : " inout " range ? _namelist " ; "
tri : " tri " range ? _ namelist " ; "
wire : " wire " range ? _namelist " ; "
assign : " assign " name " = " name " ; "
instantiation : name name " ( " [ pin ( " , " pin ) * ] " ) " " ; "
pin : " . " name " ( " name " ) "
signal : ( name | " [ " / [ 0 - 9 ] + / " : " / [ 0 - 9 ] + / " ] " name )
pin : " . " name " ( " name ? " ) "
range : " [ " / [ 0 - 9 ] + / " : " / [ 0 - 9 ] + / " ] "
_namelist : name ( " , " name ) *
name : ( / [ a - z_ ] [ a - z0 - 9 _ \\[ \\] ] * / i | / \\\\[ ^ \\t \\r \\n ] + [ \\t \\r \\n ] ( \\[ [ 0 - 9 ] + \\] ) ? / i | / 1 ' b0/i | /1 ' b1 / i )
COMMENT : " // " / [ ^ \\n ] * /
% ignore ( / \\r ? \\n / | COMMENT ) +