Skip to content

Commit

Permalink
ct (#198)
Browse files Browse the repository at this point in the history
* reuse update

* ct equi

* lint

* cov

* cov

* cov

* ct

* unit test fix

* fix ut

* lint + cov

* -1 to amx

* lint

* cov

* cov

* cov

* snlid

* snlid

* lint

* lint

* lint

* ignore W503 W504

* ignore W503 W504
  • Loading branch information
nanocoh authored Feb 12, 2025
1 parent b0ff092 commit bf0341e
Show file tree
Hide file tree
Showing 18 changed files with 209 additions and 91 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/najaeda-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
pip install coverage
- name: Lint with flake8
working-directory: ${{github.workspace}}/src/najaeda
run: flake8 --max-line-length=100 --ignore=E128 --exclude docs,examples,README
run: flake8 --max-line-length=100 --ignore E128,W504,W503 --exclude docs,examples,README
- name: Run najaeda testing with pytest
working-directory: ${{github.workspace}}/test/najaeda
env:
Expand Down
13 changes: 11 additions & 2 deletions src/najaeda/examples/dle/najaeda_dle.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from os import path
import sys
from collections import deque
import time

from najaeda import netlist
from najaeda import snl
import faulthandler

import logging

# snippet-start: dle
def apply_dle(top, keep_attributes=None):
Expand Down Expand Up @@ -49,11 +50,19 @@ def apply_dle(top, keep_attributes=None):
faulthandler.enable()
# Load design
netlist.load_primitives('xilinx')

start = time.time()
print('Starting DLE')

instances = set()
benchmarks = path.join('..', 'benchmarks')
top = netlist.load_verilog([path.join(benchmarks, 'verilog', 'vexriscv.v')])
attributes = ['DONT_TOUCH', 'KEEP', 'preserve', 'noprune']
nb_deleted = apply_dle(top, attributes)

end = time.time()
print('DLE done in %s seconds', end - start)

top.dump_verilog("./", "result.v")
print(f'deleted {len(nb_deleted)} leaves')
print(f'deleted {len(nb_deleted)} leaves')

124 changes: 71 additions & 53 deletions src/najaeda/najaeda/netlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
import logging
import hashlib
import struct
import sys
from enum import Enum

from najaeda import snl


def get_none_existent():
return sys.maxsize


def consistent_hash(obj):
def default_serializer(o):
if isinstance(o, (str, int, float, bool, type(None))):
Expand Down Expand Up @@ -40,14 +45,14 @@ def hash_object(o):


def get_snl_instance_from_id_list(id_list: list) -> snl.SNLInstance:
top = snl.SNLUniverse.get().getTopDesign()
design = top
instance = None
for id in id_list:
instance = design.getInstanceByID(id)
assert instance is not None
design = instance.getModel()
return instance
design = snl.SNLUniverse.get().getTopDesign()
# instance = None
# for id in id_list:
# instance = design.getInstanceByID(id)
# assert instance is not None
# design = instance.getModel()
# return instance
return design.getInstanceByIDList(id_list)


def get_snl_path_from_id_list(id_list: list) -> snl.SNLPath:
Expand Down Expand Up @@ -110,10 +115,10 @@ def get_inst_terms(self):
"""
if self.equi is not None:
for term in self.equi.getInstTermOccurrences():
yield Term(
snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
term.getInstTerm().getBitTerm(),
)
path = term.getPath().getPathIDs()
path.append(term.getInstTerm().getInstance().getID())
yield Term(path,
term.getInstTerm().getBitTerm())

def get_top_terms(self):
"""Iterate over the top terminals of this equipotential.
Expand All @@ -131,39 +136,35 @@ def get_leaf_readers(self):
direction = term.getInstTerm().getDirection()
if direction != snl.SNLTerm.Direction.Output:
if term.getInstTerm().getInstance().getModel().isLeaf():
yield Term(
snl.SNLPath(
term.getPath(), term.getInstTerm().getInstance()
),
term.getInstTerm().getBitTerm(),
)
path = term.getPath().getPathIDs()
path.append(term.getInstTerm().getInstance().getID())
yield Term(path,
term.getInstTerm().getBitTerm())

def get_leaf_drivers(self):
if self.equi is not None:
for term in self.equi.getInstTermOccurrences():
direction = term.getInstTerm().getDirection()
if direction != snl.SNLTerm.Direction.Input:
if term.getInstTerm().getInstance().getModel().isLeaf():
yield Term(
snl.SNLPath(
term.getPath(), term.getInstTerm().getInstance()
),
term.getInstTerm().getBitTerm(),
)
path = term.getPath().getPathIDs()
path.append(term.getInstTerm().getInstance().getID())
yield Term(path,
term.getInstTerm().getBitTerm())

def get_top_readers(self):
if self.equi is not None:
for term in self.equi.getTerms():
direction = term.getDirection()
if direction != snl.SNLTerm.Direction.Input:
yield Term(snl.SNLPath(), term)
yield Term([], term)

def get_top_drivers(self):
if self.equi is not None:
for term in self.equi.getTerms():
direction = term.getDirection()
if direction != snl.SNLTerm.Direction.Output:
yield Term(snl.SNLPath(), term)
yield Term([], term)


class Net:
Expand Down Expand Up @@ -344,10 +345,11 @@ def get_inst_terms(self):
"""
if hasattr(self, "net_concat"):
raise ValueError("Cannot get inst terms from a net_concat")
path = self.pathIDs.copy()
for term in self.net.getInstTerms():
path = self.pathIDs.copy()
path.append(term.getInstance().getID())
yield Term(path, term.getBitTerm())
path.pop()

def get_design_terms(self):
"""
Expand Down Expand Up @@ -375,12 +377,12 @@ def get_snl_term_for_ids(pathIDs, termIDs):
model = snl.SNLUniverse.get().getTopDesign()
else:
model = path.getTailInstance().getModel()
if termIDs[1] == -1:
if termIDs[1] == get_none_existent():
return model.getTermByID(termIDs[0])
else:
snlterm = model.getTermByID(termIDs[0])
if isinstance(snlterm, snl.SNLBusTerm):
return snlterm.getBit(termIDs[1])
return snlterm.getBusTermBit(termIDs[1])
else:
return snlterm

Expand All @@ -391,12 +393,12 @@ def get_snl_term_for_ids_with_path(path, termIDs):
model = snl.SNLUniverse.get().getTopDesign()
else:
model = path.getTailInstance().getModel()
if termIDs[1] == -1:
if termIDs[1] == get_none_existent():
return model.getTermByID(termIDs[0])
else:
snlterm = model.getTermByID(termIDs[0])
if isinstance(snlterm, snl.SNLBusTerm):
return snlterm.getBit(termIDs[1])
return snlterm.getBusTermBit(termIDs[1])
else:
return snlterm

Expand All @@ -407,19 +409,12 @@ class Term:
INOUT = snl.SNLTerm.Direction.InOut

def __init__(self, path, term):
self.termIDs = []
if isinstance(term, snl.SNLBusTerm):
self.termIDs = [term.getID(), -1]
else:
self.termIDs = [term.getID(), term.getBit()]

if isinstance(path, snl.SNLPath):
if path.size() > 0:
self.pathIDs = path.getPathIDs()
else:
self.pathIDs = []
elif isinstance(path, list):
self.pathIDs = path.copy()
# self.termIDs = []
# if isinstance(term, snl.SNLBusTerm):
# self.termIDs = [term.getID(), -1]
# else:
self.termIDs = [term.getID(), term.getBit()]
self.pathIDs = path.copy()

def __eq__(self, other) -> bool:
return self.pathIDs == other.pathIDs and self.termIDs == other.termIDs
Expand Down Expand Up @@ -668,7 +663,7 @@ def get_bit(self, index: int):
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
return Term(
self.pathIDs,
get_snl_term_for_ids(self.pathIDs, self.termIDs).getBit(index),
get_snl_term_for_ids(self.pathIDs, self.termIDs).getBusTermBit(index),
)
return None

Expand Down Expand Up @@ -771,13 +766,23 @@ class Instance:
"""

def __init__(self, path=snl.SNLPath()):
self.inst = None
self.revisionCount = 0
self.SNLID = [0, 0, 0, 0, 0, 0]
if isinstance(path, snl.SNLPath):
if path.size() > 0:
self.pathIDs = path.getPathIDs()
self.revisionCount = path.getTailInstance().getModel().getRevisionCount()
self.inst = path.getTailInstance()
else:
self.pathIDs = []
elif isinstance(path, list):
self.pathIDs = path.copy()
if len(path) > 0:
self.inst = get_snl_instance_from_id_list(path)
self.revisionCount = self.inst.getModel().getRevisionCount()
if self.inst is not None:
self.SNLID = self.inst.getModel().getSNLID()

def __eq__(self, other) -> bool:
return self.pathIDs == other.pathIDs
Expand Down Expand Up @@ -889,11 +894,24 @@ def is_inv(self) -> bool:
"""
return self.__get_snl_model().isInv()

def is_basic_primitive(instance):
design = instance.__get_snl_model()
return (
design.isConst0() or design.isConst1() or design.isBuf() or design.isInv()
)

def __get_snl_model(self):
if self.is_top():
return snl.SNLUniverse.get().getTopDesign()
instance = get_snl_instance_from_id_list(self.pathIDs)
return instance.getModel()
if (
self.inst.getModel().getRevisionCount() != self.revisionCount or
self.inst.getModel().getSNLID() != self.SNLID
):
self.inst = get_snl_instance_from_id_list(self.pathIDs)
self.revisionCount = self.inst.getModel().getRevisionCount()
self.SNLID = self.inst.getModel().getSNLID()

return self.inst.getModel()

def __get_leaf_snl_object(self):
if self.is_top():
Expand Down Expand Up @@ -936,10 +954,11 @@ def get_child_instances(self):
:return: an iterator over the child instances of this instance.
:rtype: Iterator[Instance]
"""
path = get_snl_path_from_id_list(self.pathIDs)
for inst in self.__get_snl_model().getInstances():
path = self.pathIDs.copy()
path.append(inst.getID())
yield Instance(path)
path_child = snl.SNLPath(path, inst)
yield Instance(path_child)
# path.pop()

def get_number_of_child_instances(self) -> int:
"""
Expand Down Expand Up @@ -1198,7 +1217,7 @@ def create_term(self, name: str, direction: snl.SNLTerm.Direction) -> Term:
path = get_snl_path_from_id_list(self.pathIDs)
design = self.__get_snl_model()
newSNLTerm = snl.SNLScalarTerm.create(design, direction, name)
return Term(path, newSNLTerm)
return Term(path.getPathIDs(), newSNLTerm)

def create_output_term(self, name: str) -> Term:
"""Create an output Term in this Instance with the given name.
Expand Down Expand Up @@ -1239,10 +1258,9 @@ def create_bus_term(self, name: str, msb: int, lsb: int, direction) -> Term:
path = get_snl_path_from_id_list(self.pathIDs)
if path.size() > 0:
snl.SNLUniquifier(path)
path = get_snl_path_from_id_list(self.pathIDs)
design = self.__get_snl_model()
newSNLTerm = snl.SNLBusTerm.create(design, direction, msb, lsb, name)
return Term(path, newSNLTerm)
return Term(self.pathIDs, newSNLTerm)

def create_inout_bus_term(self, name: str, msb: int, lsb: int) -> Term:
"""Create an inout bus Term in this Instance with the given name, msb and lsb.
Expand Down
6 changes: 2 additions & 4 deletions src/najaeda/najaeda/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,8 @@ def add_ins_stats(self, ins_stats):
)


def is_basic_primitive(design):
return (
design.is_const0() or design.is_const1() or design.is_buf() or design.is_inv()
)
def is_basic_primitive(instance):
return instance.is_basic_primitive()


def compute_instance_stats(instance, instances_stats):
Expand Down
35 changes: 33 additions & 2 deletions src/snl/python/snl_wrapping/PySNLBusTerm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "PyInterface.h"
#include "PySNLDesign.h"
#include "PySNLBusTermBit.h"
#include <limits>

#include "SNLBusTerm.h"
#include "SNLBusTermBit.h"
Expand Down Expand Up @@ -49,12 +50,40 @@ static PyObject* PySNLBusTerm_create(PyObject*, PyObject* args) {
return PySNLBusTerm_Link(term);
}

// To retrun getBit but to rename the function as getBusTermBit
PyObject* PySNLBusTerm_getBusTermBit(PySNLBusTerm* self, PyObject* args) {
PyObject* arg0 = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLBusTerm.getBit", &arg0)) {
setError("malformed SNLBusTerm getBit method");
return nullptr;
}
SNLID::Bit bit = 0;
if (PyLong_Check(arg0)) {
bit = PyLong_AsLong(arg0);
} else {
setError("SNLBusTerm getBit accepts an integer as first argument");
return nullptr;
}
SNLBusTermBit* bitTerm = nullptr;
// LCOV_EXCL_START
TRY
bitTerm = (static_cast<naja::SNL::SNLBusTerm*>(self->parent_.parent_.parent_.object_))->getBit(bit);
SNLCATCH
// LCOV_EXCL_STOP
return PySNLBusTermBit_Link(bitTerm);
}

// Function named getBit with no args that returns -1 int
PyObject* PySNLBusTerm_getBit(PySNLBusTerm* self) {
return PyLong_FromLong(std::numeric_limits<long>::max());
}

DirectGetIntMethod(PySNLBusTerm_getMSB, getMSB, PySNLBusTerm, SNLBusTerm)
DirectGetIntMethod(PySNLBusTerm_getLSB, getLSB, PySNLBusTerm, SNLBusTerm)
DirectGetIntMethod(PySNLBusTerm_getID, getID, PySNLBusTerm, SNLBusTerm)
DirectGetIntMethod(PySNLBusTerm_getFlatID, getFlatID, PySNLBusTerm, SNLBusTerm)

GetObjectByIndex(BusTerm, BusTermBit, Bit)
//GetObjectByIndex(BusTerm, BusTermBit, Bit)

DBoLinkCreateMethod(SNLBusTerm)
DBoDeallocMethod(SNLBusTerm)
Expand All @@ -67,7 +96,9 @@ PyMethodDef PySNLBusTerm_Methods[] = {
"get SNLBusTerm MSB value"},
{ "getLSB", (PyCFunction)PySNLBusTerm_getLSB, METH_NOARGS,
"get SNLBusTerm LSB value"},
{ "getBit", (PyCFunction)PySNLBusTerm_getBit, METH_VARARGS,
{ "getBit", (PyCFunction)PySNLBusTerm_getBit, METH_NOARGS,
"retruns -1"},
{ "getBusTermBit", (PyCFunction)PySNLBusTerm_getBusTermBit, METH_VARARGS,
"get SNLBusTerm Bit, returns SNLBusTermBit"},
{ "getID", (PyCFunction)PySNLBusTerm_getID, METH_NOARGS,
"get SNLBusTerm ID value"},
Expand Down
Loading

0 comments on commit bf0341e

Please sign in to comment.