fixes for IWLS benchmark netlists and older STIL files
This commit is contained in:
1 parent
c9445f2d79
commit
b17ab2d148
5 files changed
+76
-58
No files matched your search
@@ -107,10 +107,10 @@ class LogicSim:
|
|||||||
sim.capture(state_bp)
|
sim.capture(state_bp)
|
||||||
|
|
||||||
:param inject_cb: A callback function for manipulating intermediate signal values.
|
:param inject_cb: A callback function for manipulating intermediate signal values.
|
||||||
This function is called with a line index and its new logic values (in bit-parallel format) after
|
This function is called with a line and its new logic values (in bit-parallel format) after
|
||||||
evaluation of a node. The callback may manipulate the given values in-place, the simulation
|
evaluation of a node. The callback may manipulate the given values in-place, the simulation
|
||||||
resumes with the manipulated values after the callback returns.
|
resumes with the manipulated values after the callback returns.
|
||||||
:type inject_cb: ``f(int, ndarray)``
|
:type inject_cb: ``f(Line, ndarray)``
|
||||||
"""
|
"""
|
||||||
for node in self.circuit.topological_order():
|
for node in self.circuit.topological_order():
|
||||||
if self.state_epoch[node] != self.epoch: continue
|
if self.state_epoch[node] != self.epoch: continue
|
||||||
|
|||||||
+3
-5
@@ -9,6 +9,7 @@ Call :py:func:`DelayFile.annotation` to match the intermediate representation to
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
import re
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from lark import Lark, Transformer
|
from lark import Lark, Transformer
|
||||||
@@ -93,13 +94,11 @@ class DelayFile:
|
|||||||
if cell is None:
|
if cell is None:
|
||||||
log.warn(f'Cell from SDF not found in circuit: {cn}')
|
log.warn(f'Cell from SDF not found in circuit: {cn}')
|
||||||
continue
|
continue
|
||||||
|
ipn = re.sub(r'\((neg|pos)edge ([^)]+)\)', r'\2', ipn)
|
||||||
ipin = tlib.pin_index(cell.kind, ipn)
|
ipin = tlib.pin_index(cell.kind, ipn)
|
||||||
opin = tlib.pin_index(cell.kind, opn)
|
opin = tlib.pin_index(cell.kind, opn)
|
||||||
kind = cell.kind.lower()
|
kind = cell.kind.lower()
|
||||||
|
|
||||||
ipn2 = ipn.replace('(posedge A1)', 'A1').replace('(negedge A1)', 'A1')\
|
|
||||||
.replace('(posedge A2)', 'A2').replace('(negedge A2)', 'A2')
|
|
||||||
|
|
||||||
def add_delays(_line):
|
def add_delays(_line):
|
||||||
if _line is not None:
|
if _line is not None:
|
||||||
timing[_line, :, 0] += select_del(delvals, 0)
|
timing[_line, :, 0] += select_del(delvals, 0)
|
||||||
@@ -107,13 +106,12 @@ class DelayFile:
|
|||||||
|
|
||||||
take_avg = False
|
take_avg = False
|
||||||
if kind.startswith('sdff'):
|
if kind.startswith('sdff'):
|
||||||
if not ipn.startswith('(posedge CLK'):
|
if not ipn.startswith('CLK'):
|
||||||
continue
|
continue
|
||||||
if ffdelays and (len(cell.outs) > opin):
|
if ffdelays and (len(cell.outs) > opin):
|
||||||
add_delays(cell.outs[opin])
|
add_delays(cell.outs[opin])
|
||||||
else:
|
else:
|
||||||
if kind.startswith(('xor', 'xnor')):
|
if kind.startswith(('xor', 'xnor')):
|
||||||
ipin = tlib.pin_index(cell.kind, ipn2)
|
|
||||||
# print(ipn, ipin, times[cell.i_lines[ipin], 0, 0])
|
# print(ipn, ipin, times[cell.i_lines[ipin], 0, 0])
|
||||||
take_avg = timing[cell.ins[ipin]].sum() > 0
|
take_avg = timing[cell.ins[ipin]].sum() > 0
|
||||||
add_delays(cell.ins[ipin])
|
add_delays(cell.ins[ipin])
|
||||||
|
|||||||
+6
-6
@@ -49,11 +49,10 @@ class StilFile:
|
|||||||
for si_port in self.si_ports:
|
for si_port in self.si_ports:
|
||||||
if si_port in call.parameters:
|
if si_port in call.parameters:
|
||||||
sload[si_port] = call.parameters[si_port].replace('\n', '')
|
sload[si_port] = call.parameters[si_port].replace('\n', '')
|
||||||
if call.name.endswith('_launch') or call.name.endswith('_capture'):
|
if call.name.endswith('_launch'):
|
||||||
if len(launch) == 0:
|
launch = dict((k, v.replace('\n', '')) for k, v in call.parameters.items())
|
||||||
launch = dict((k, v.replace('\n', '')) for k, v in call.parameters.items())
|
if call.name.endswith('_capture'):
|
||||||
else:
|
capture = dict((k, v.replace('\n', '')) for k, v in call.parameters.items())
|
||||||
capture = dict((k, v.replace('\n', '')) for k, v in call.parameters.items())
|
|
||||||
|
|
||||||
def _maps(self, c):
|
def _maps(self, c):
|
||||||
interface = list(c.interface) + [n for n in c.nodes if 'DFF' in n.kind]
|
interface = list(c.interface) + [n for n in c.nodes if 'DFF' in n.kind]
|
||||||
@@ -197,7 +196,7 @@ class StilTransformer(Transformer):
|
|||||||
|
|
||||||
|
|
||||||
GRAMMAR = r"""
|
GRAMMAR = r"""
|
||||||
start: "STIL" FLOAT _ignore _block*
|
start: "STIL" FLOAT ( _ignore | ";" ) _block*
|
||||||
_block: signal_groups | scan_structures | pattern
|
_block: signal_groups | scan_structures | pattern
|
||||||
| "Header" _ignore
|
| "Header" _ignore
|
||||||
| "Signals" _ignore
|
| "Signals" _ignore
|
||||||
@@ -206,6 +205,7 @@ GRAMMAR = r"""
|
|||||||
| "PatternExec" _ignore
|
| "PatternExec" _ignore
|
||||||
| "Procedures" _ignore
|
| "Procedures" _ignore
|
||||||
| "MacroDefs" _ignore
|
| "MacroDefs" _ignore
|
||||||
|
| "UserKeywords" /[a-zA-Z]*;/
|
||||||
|
|
||||||
signal_groups: "SignalGroups" "{" signal_group* "}"
|
signal_groups: "SignalGroups" "{" signal_group* "}"
|
||||||
signal_group: quoted "=" "'" quoted ( "+" quoted)* "'" _ignore? ";"?
|
signal_group: quoted "=" "'" quoted ( "+" quoted)* "'" _ignore? ";"?
|
||||||
|
|||||||
+14
-6
@@ -29,20 +29,28 @@ class TechLib:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def pin_index(kind, pin):
|
def pin_index(kind, pin):
|
||||||
"""Returns a pin list position for a given node kind and pin name."""
|
"""Returns a pin list position for a given node kind and pin name."""
|
||||||
|
if kind[:3] in ('OAI', 'AOI'):
|
||||||
|
if pin[0] == 'A': return int(pin[1])
|
||||||
|
if pin[0] == 'B': return int(pin[1]) + int(kind[4])
|
||||||
for prefix, pins, index in [('HADD', ('B0', 'SO'), 1),
|
for prefix, pins, index in [('HADD', ('B0', 'SO'), 1),
|
||||||
('MUX21', ('S',), 2),
|
('MUX21', ('S',), 2),
|
||||||
|
('MX2', ('S0',), 2),
|
||||||
|
('TBUF', ('OE',), 1),
|
||||||
|
('TINV', ('OE',), 1),
|
||||||
('DFF', ('QN',), 1),
|
('DFF', ('QN',), 1),
|
||||||
|
('DFF', ('D',), 0),
|
||||||
|
('SDFF', ('D',), 0),
|
||||||
('SDFF', ('QN',), 1),
|
('SDFF', ('QN',), 1),
|
||||||
('SDFF', ('CLK',), 3),
|
('SDFF', ('CLK',), 3),
|
||||||
('SDFF', ('RSTB',), 4),
|
('SDFF', ('RSTB',), 4),
|
||||||
('SDFF', ('SETB',), 5)]:
|
('SDFF', ('SETB',), 5)]:
|
||||||
if kind.startswith(prefix) and pin in pins: return index
|
if kind.startswith(prefix) and pin in pins: return index
|
||||||
for index, pins in enumerate([('A1', 'IN1', 'D', 'S', 'INP', 'A', 'Q', 'QN', 'Y', 'Z', 'ZN'),
|
for index, pins in enumerate([('A1', 'IN1', 'A', 'S', 'INP', 'Q', 'QN', 'Y', 'Z', 'ZN'),
|
||||||
('A2', 'IN2', 'CLK', 'CO', 'SE', 'B'),
|
('A2', 'IN2', 'B', 'CK', 'CLK', 'CO', 'SE'),
|
||||||
('A3', 'IN3', 'RSTB', 'CI', 'SI'),
|
('A3', 'IN3', 'C', 'RN', 'RSTB', 'CI', 'SI'),
|
||||||
('A4', 'IN4', 'SETB'),
|
('A4', 'IN4', 'D', 'SN', 'SETB'),
|
||||||
('A5', 'IN5'),
|
('A5', 'IN5', 'E'),
|
||||||
('A6', 'IN6')]):
|
('A6', 'IN6', 'F')]):
|
||||||
if pin in pins: return index
|
if pin in pins: return index
|
||||||
raise ValueError(f'Unknown pin index for {kind}.{pin}')
|
raise ValueError(f'Unknown pin index for {kind}.{pin}')
|
||||||
|
|
||||||
|
|||||||
+51
-39
@@ -8,7 +8,7 @@ from collections import namedtuple
|
|||||||
|
|
||||||
from lark import Lark, Transformer
|
from lark import Lark, Transformer
|
||||||
|
|
||||||
from . import readtext
|
from . import log, readtext
|
||||||
from .circuit import Circuit, Node, Line
|
from .circuit import Circuit, Node, Line
|
||||||
from .techlib import TechLib
|
from .techlib import TechLib
|
||||||
|
|
||||||
@@ -17,27 +17,21 @@ Instantiation = namedtuple('Instantiation', ['type', 'name', 'pins'])
|
|||||||
|
|
||||||
class SignalDeclaration:
|
class SignalDeclaration:
|
||||||
|
|
||||||
def __init__(self, kind, tokens):
|
def __init__(self, kind, name, rnge=None):
|
||||||
self.left = None
|
self.left = None
|
||||||
self.right = None
|
self.right = None
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
if len(tokens.children) == 1:
|
self.basename = name
|
||||||
self.basename = tokens.children[0]
|
self.rnge = rnge
|
||||||
else:
|
|
||||||
self.basename = tokens.children[2]
|
|
||||||
self.left = int(tokens.children[0].value)
|
|
||||||
self.right = int(tokens.children[1].value)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def names(self):
|
def names(self):
|
||||||
if self.left is None:
|
if self.rnge is None:
|
||||||
return [self.basename]
|
return [self.basename]
|
||||||
if self.left <= self.right:
|
return [f'{self.basename}[{i}]' for i in self.rnge]
|
||||||
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)]
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"{self.kind}:{self.basename}[{self.left}:{self.right}]"
|
return f"{self.kind}:{self.basename}[{self.rnge}]"
|
||||||
|
|
||||||
|
|
||||||
class VerilogTransformer(Transformer):
|
class VerilogTransformer(Transformer):
|
||||||
@@ -57,28 +51,33 @@ class VerilogTransformer(Transformer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def instantiation(args):
|
def instantiation(args):
|
||||||
return Instantiation(args[0], args[1],
|
return Instantiation(args[0], args[1],
|
||||||
dict((pin.children[0], pin.children[1]) for pin in args[2:]))
|
dict((pin.children[0],
|
||||||
|
pin.children[1]) for pin in args[2:] if len(pin.children) > 1))
|
||||||
|
|
||||||
def input(self, args):
|
def range(self, args):
|
||||||
for sd in [SignalDeclaration('input', signal) for signal in args]:
|
left = int(args[0].value)
|
||||||
self._signal_declarations[sd.basename] = sd
|
right = int(args[1].value)
|
||||||
|
return range(left, right+1) if left <= right else range(left, right-1, -1)
|
||||||
|
|
||||||
def inout(self, args):
|
def declaration(self, kind, args):
|
||||||
for sd in [SignalDeclaration('input', signal) for signal in args]: # just treat as input
|
rnge = None
|
||||||
self._signal_declarations[sd.basename] = sd
|
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):
|
def input(self, args): self.declaration("input", args)
|
||||||
for sd in [SignalDeclaration('output', signal) for signal in args]:
|
def output(self, args): self.declaration("output", args)
|
||||||
self._signal_declarations[sd.basename] = sd
|
def inout(self, args): self.declaration("input", args) # just treat as input
|
||||||
|
def wire(self, args): self.declaration("wire", args)
|
||||||
def wire(self, args):
|
|
||||||
for sd in [SignalDeclaration('wire', signal) for signal in args]:
|
|
||||||
self._signal_declarations[sd.basename] = sd
|
|
||||||
|
|
||||||
def module(self, args):
|
def module(self, args):
|
||||||
c = Circuit(args[0])
|
c = Circuit(args[0])
|
||||||
positions = {}
|
positions = {}
|
||||||
pos = 0
|
pos = 0
|
||||||
|
const_count = 0
|
||||||
for intf_sig in args[1].children:
|
for intf_sig in args[1].children:
|
||||||
for name in self._signal_declarations[intf_sig].names:
|
for name in self._signal_declarations[intf_sig].names:
|
||||||
positions[name] = pos
|
positions[name] = pos
|
||||||
@@ -107,15 +106,24 @@ class VerilogTransformer(Transformer):
|
|||||||
elif s2 in c.forks:
|
elif s2 in c.forks:
|
||||||
assert s1 not in c.forks, 'assignment between two driven signals'
|
assert s1 not in c.forks, 'assignment between two driven signals'
|
||||||
Line(c, c.forks[s2], Node(c, s1))
|
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
|
for stmt in args[2:]: # pass 2: connect signals to readers
|
||||||
if isinstance(stmt, Instantiation):
|
if isinstance(stmt, Instantiation):
|
||||||
for p, s in stmt.pins.items():
|
for p, s in stmt.pins.items():
|
||||||
n = c.cells[stmt.name]
|
n = c.cells[stmt.name]
|
||||||
if self.tlib.pin_is_output(n.kind, p): continue
|
if self.tlib.pin_is_output(n.kind, p): continue
|
||||||
if s.startswith("1'b"):
|
if s.startswith("1'b"):
|
||||||
const = f'__const{s[3]}__'
|
cname = f'__const{s[3]}_{const_count}__'
|
||||||
if const not in c.cells:
|
cnode = Node(c, cname, f'__const{s[3]}__')
|
||||||
Line(c, Node(c, const, const), Node(c, s))
|
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]
|
fork = c.forks[s]
|
||||||
if self.branchforks:
|
if self.branchforks:
|
||||||
branchfork = Node(c, fork.name + "~" + n.name + "/" + p)
|
branchfork = Node(c, fork.name + "~" + n.name + "/" + p)
|
||||||
@@ -125,7 +133,10 @@ class VerilogTransformer(Transformer):
|
|||||||
for sd in self._signal_declarations.values():
|
for sd in self._signal_declarations.values():
|
||||||
if sd.kind == 'output':
|
if sd.kind == 'output':
|
||||||
for name in sd.names:
|
for name in sd.names:
|
||||||
Line(c, c.forks[name], c.cells[name])
|
if name not in c.forks:
|
||||||
|
log.warn(f'Output not driven: {name}')
|
||||||
|
else:
|
||||||
|
Line(c, c.forks[name], c.cells[name])
|
||||||
return c
|
return c
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -135,18 +146,19 @@ class VerilogTransformer(Transformer):
|
|||||||
GRAMMAR = """
|
GRAMMAR = """
|
||||||
start: (module)*
|
start: (module)*
|
||||||
module: "module" name parameters ";" (_statement)* "endmodule"
|
module: "module" name parameters ";" (_statement)* "endmodule"
|
||||||
parameters: "(" [ name ( "," name )* ] ")"
|
parameters: "(" [ _namelist ] ")"
|
||||||
_statement: input | output | inout | tri | wire | assign | instantiation
|
_statement: input | output | inout | tri | wire | assign | instantiation
|
||||||
input: "input" signal ( "," signal )* ";"
|
input: "input" range? _namelist ";"
|
||||||
output: "output" signal ( "," signal )* ";"
|
output: "output" range? _namelist ";"
|
||||||
inout: "inout" signal ( "," signal )* ";"
|
inout: "inout" range? _namelist ";"
|
||||||
tri: "tri" name ";"
|
tri: "tri" range? _namelist ";"
|
||||||
wire: "wire" signal ( "," signal )* ";"
|
wire: "wire" range? _namelist ";"
|
||||||
assign: "assign" name "=" name ";"
|
assign: "assign" name "=" name ";"
|
||||||
instantiation: name name "(" [ pin ( "," pin )* ] ")" ";"
|
instantiation: name name "(" [ pin ( "," pin )* ] ")" ";"
|
||||||
pin: "." name "(" name ")"
|
pin: "." name "(" name? ")"
|
||||||
signal: ( name | "[" /[0-9]+/ ":" /[0-9]+/ "]" 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 )
|
name: ( /[a-z_][a-z0-9_\\[\\]]*/i | /\\\\[^\\t \\r\\n]+[\\t \\r\\n](\\[[0-9]+\\])?/i | /1'b0/i | /1'b1/i )
|
||||||
COMMENT: "//" /[^\\n]*/
|
COMMENT: "//" /[^\\n]*/
|
||||||
%ignore ( /\\r?\\n/ | COMMENT )+
|
%ignore ( /\\r?\\n/ | COMMENT )+
|
||||||
|
|||||||
Reference in new issue
Block a user