mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'private/dev' into control-logic-pull
This commit is contained in:
commit
13bdae2e30
|
|
@ -4,52 +4,54 @@ jobs:
|
|||
scn4me_subm:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Check out repository
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v1
|
||||
- name: SCMOS test
|
||||
run: |
|
||||
. /home/github-runner/setup-paths.sh
|
||||
export OPENRAM_HOME="`pwd`/compiler"
|
||||
export OPENRAM_TECH="`pwd`/technology:/software/PDKs/skywater-tech"
|
||||
export OPENRAM_TMP="`pwd`/scn4me_subm"
|
||||
python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 48 -t scn4m_subm
|
||||
export OPENRAM_TMP="${{ github.workspace }}/scn4me_subm_temp"
|
||||
#python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 12 -t scn4m_subm
|
||||
$OPENRAM_HOME/tests/regress.py -j 12 -t scn4m_subm
|
||||
- name: Archive
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: scn4me_subm Archives
|
||||
path: $OPENRAM_TMP/
|
||||
path: ${{ github.workspace }}/scn4me_subm_temp/*/
|
||||
freepdk45:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Check out repository
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v1
|
||||
- name: FreePDK45 test
|
||||
run: |
|
||||
. /home/github-runner/setup-paths.sh
|
||||
export OPENRAM_HOME="`pwd`/compiler"
|
||||
export OPENRAM_TECH="`pwd`/technology:/software/PDKs/skywater-tech"
|
||||
export OPENRAM_TMP="`pwd`/freepdk45"
|
||||
python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 48 -t freepdk45
|
||||
export OPENRAM_TMP="${{ github.workspace }}/freepdk45_temp"
|
||||
#python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 12 -t freepdk45
|
||||
$OPENRAM_HOME/tests/regress.py -j 12 -t freepdk45
|
||||
- name: Archive
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: FreePDK45 Archives
|
||||
path: $OPENRAM_TMP/
|
||||
coverage:
|
||||
if: ${{ always() }}
|
||||
needs: [scn4me_subm, freepdk45]
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Coverage stats
|
||||
run: |
|
||||
python3-coverage combine
|
||||
python3-coverage report
|
||||
python3-coverage html -d coverage_html
|
||||
- name: Archive coverage
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: code-coverage-report
|
||||
path: coverage_html/
|
||||
path: ${{ github.workspace }}/freepdk45_temp/*/
|
||||
# coverage_stats:
|
||||
# if: ${{ always() }}
|
||||
# needs: [scn4me_subm, freepdk45]
|
||||
# runs-on: self-hosted
|
||||
# steps:
|
||||
# - name: Coverage stats
|
||||
# run: |
|
||||
# python3-coverage combine
|
||||
# python3-coverage report
|
||||
# python3-coverage html -d ${{ github.workspace }}/coverage_html
|
||||
# - name: Archive coverage
|
||||
# uses: actions/upload-artifact@v2
|
||||
# with:
|
||||
# name: code-coverage-report
|
||||
# path: ${{ github.workspace }}/coverage_html/
|
||||
|
||||
|
|
|
|||
|
|
@ -146,10 +146,10 @@ class sense_amp_array(design.design):
|
|||
inst = self.local_insts[i]
|
||||
|
||||
for gnd_pin in inst.get_pins("gnd"):
|
||||
self.copy_power_pin(gnd_pin, directions=("V", "V"))
|
||||
self.copy_power_pin(gnd_pin)
|
||||
|
||||
for vdd_pin in inst.get_pins("vdd"):
|
||||
self.copy_power_pin(vdd_pin, directions=("V", "V"))
|
||||
self.copy_power_pin(vdd_pin)
|
||||
|
||||
bl_pin = inst.get_pin(inst.mod.get_bl_names())
|
||||
br_pin = inst.get_pin(inst.mod.get_br_names())
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#
|
||||
from enum import Enum
|
||||
from vector3d import vector3d
|
||||
import debug
|
||||
|
||||
|
||||
class direction(Enum):
|
||||
NORTH = 1
|
||||
|
|
@ -20,31 +22,30 @@ class direction(Enum):
|
|||
SOUTHEAST = 9
|
||||
SOUTHWEST = 10
|
||||
|
||||
|
||||
def get_offset(direct):
|
||||
"""
|
||||
Returns the vector offset for a given direction.
|
||||
"""
|
||||
if direct==direction.NORTH:
|
||||
offset = vector3d(0,1,0)
|
||||
offset = vector3d(0, 1, 0)
|
||||
elif direct==direction.SOUTH:
|
||||
offset = vector3d(0,-1,0)
|
||||
offset = vector3d(0, -1 ,0)
|
||||
elif direct==direction.EAST:
|
||||
offset = vector3d(1,0,0)
|
||||
offset = vector3d(1, 0, 0)
|
||||
elif direct==direction.WEST:
|
||||
offset = vector3d(-1,0,0)
|
||||
offset = vector3d(-1, 0, 0)
|
||||
elif direct==direction.UP:
|
||||
offset = vector3d(0,0,1)
|
||||
offset = vector3d(0, 0, 1)
|
||||
elif direct==direction.DOWN:
|
||||
offset = vector3d(0,0,-1)
|
||||
offset = vector3d(0, 0, -1)
|
||||
elif direct==direction.NORTHEAST:
|
||||
offset = vector3d(1,1,0)
|
||||
offset = vector3d(1, 1, 0)
|
||||
elif direct==direction.NORTHWEST:
|
||||
offset = vector3d(-1,1,0)
|
||||
offset = vector3d(-1, 1, 0)
|
||||
elif direct==direction.SOUTHEAST:
|
||||
offset = vector3d(1,-1,0)
|
||||
offset = vector3d(1, -1, 0)
|
||||
elif direct==direction.SOUTHWEST:
|
||||
offset = vector3d(-1,-1,0)
|
||||
offset = vector3d(-1, -1, 0)
|
||||
else:
|
||||
debug.error("Invalid direction {}".format(direct))
|
||||
|
||||
|
|
@ -67,8 +68,8 @@ class direction(Enum):
|
|||
return [direction.get_offset(d) for d in direction.all_directions()]
|
||||
|
||||
def all_neighbors(cell):
|
||||
return [cell+x for x in direction.all_offsets()]
|
||||
return [cell + x for x in direction.all_offsets()]
|
||||
|
||||
def cardinal_neighbors(cell):
|
||||
return [cell+x for x in direction.cardinal_offsets()]
|
||||
return [cell + x for x in direction.cardinal_offsets()]
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ class pin_group:
|
|||
# Remove any redundant pins (i.e. contained in other pins)
|
||||
self.remove_redundant_pins()
|
||||
|
||||
|
||||
self.router = router
|
||||
# These are the corresponding pin grids for each pin group.
|
||||
self.grids = set()
|
||||
|
|
@ -101,13 +100,11 @@ class pin_group:
|
|||
if local_debug:
|
||||
debug.info(0, "INITIAL: {}".format(pin_list))
|
||||
|
||||
new_pin_list = pin_list.copy()
|
||||
|
||||
remove_indices = set()
|
||||
add_indices = set(range(len(pin_list)))
|
||||
# This is n^2, but the number is small
|
||||
for index1, pin1 in enumerate(pin_list):
|
||||
# If we remove this pin, it can't contain other pins
|
||||
if index1 in remove_indices:
|
||||
if index1 not in add_indices:
|
||||
continue
|
||||
|
||||
for index2, pin2 in enumerate(pin_list):
|
||||
|
|
@ -117,17 +114,15 @@ class pin_group:
|
|||
if index1 == index2:
|
||||
continue
|
||||
# If we already removed it, can't remove it again...
|
||||
if index2 in remove_indices:
|
||||
if index2 not in add_indices:
|
||||
continue
|
||||
|
||||
if pin1.contains(pin2):
|
||||
if local_debug:
|
||||
debug.info(0, "{0} contains {1}".format(pin1, pin2))
|
||||
remove_indices.add(index2)
|
||||
add_indices.remove(index2)
|
||||
|
||||
# Remove them in decreasing order to not invalidate the indices
|
||||
for i in sorted(remove_indices, reverse=True):
|
||||
del new_pin_list[i]
|
||||
new_pin_list = [pin_list[x] for x in add_indices]
|
||||
|
||||
if local_debug:
|
||||
debug.info(0, "FINAL : {}".format(new_pin_list))
|
||||
|
|
@ -423,13 +418,15 @@ class pin_group:
|
|||
# We may have started with an empty set
|
||||
debug.check(len(self.grids) > 0, "Cannot seed an grid empty set.")
|
||||
|
||||
common_blockages = self.router.get_blocked_grids() & self.grids
|
||||
|
||||
# Start with the ll and make the widest row
|
||||
row = [ll]
|
||||
# Move in dir1 while we can
|
||||
while True:
|
||||
next_cell = row[-1] + offset1
|
||||
# Can't move if not in the pin shape
|
||||
if next_cell in self.grids and next_cell not in self.router.get_blocked_grids():
|
||||
if next_cell in self.grids and next_cell not in common_blockages:
|
||||
row.append(next_cell)
|
||||
else:
|
||||
break
|
||||
|
|
@ -438,7 +435,7 @@ class pin_group:
|
|||
next_row = [x + offset2 for x in row]
|
||||
for cell in next_row:
|
||||
# Can't move if any cell is not in the pin shape
|
||||
if cell not in self.grids or cell in self.router.get_blocked_grids():
|
||||
if cell not in self.grids or cell in common_blockages:
|
||||
break
|
||||
else:
|
||||
row = next_row
|
||||
|
|
@ -619,6 +616,11 @@ class pin_group:
|
|||
# Set of track adjacent to or paritally overlap a pin (not full DRC connection)
|
||||
partial_set = set()
|
||||
|
||||
# for pin in self.pins:
|
||||
# lx = pin.lx()
|
||||
# ly = pin.by()
|
||||
# if lx > 87.9 and lx < 87.99 and ly > 18.56 and ly < 18.6:
|
||||
# breakpoint()
|
||||
for pin in self.pins:
|
||||
debug.info(4, " Converting {0}".format(pin))
|
||||
# Determine which tracks the pin overlaps
|
||||
|
|
@ -632,7 +634,8 @@ class pin_group:
|
|||
blockage_in_tracks = self.router.convert_blockage(pin)
|
||||
# Must include the pins here too because these are computed in a different
|
||||
# way than blockages.
|
||||
self.blockages.update(sufficient | insufficient | blockage_in_tracks)
|
||||
blockages = sufficient | insufficient | blockage_in_tracks
|
||||
self.blockages.update(blockages)
|
||||
|
||||
# If we have a blockage, we must remove the grids
|
||||
# Remember, this excludes the pin blockages already
|
||||
|
|
|
|||
|
|
@ -504,14 +504,21 @@ class router(router_tech):
|
|||
ll = vector(boundary[0], boundary[1])
|
||||
ur = vector(boundary[2], boundary[3])
|
||||
rect = [ll, ur]
|
||||
new_pin = pin_layout("blockage{}".format(len(self.blockages)),
|
||||
rect,
|
||||
lpp)
|
||||
new_shape = pin_layout("blockage{}".format(len(self.blockages)),
|
||||
rect,
|
||||
lpp)
|
||||
|
||||
# If there is a rectangle that is the same in the pins,
|
||||
# it isn't a blockage!
|
||||
if new_pin not in self.all_pins:
|
||||
self.blockages.append(new_pin)
|
||||
if new_shape not in self.all_pins and not self.pin_contains(new_shape):
|
||||
self.blockages.append(new_shape)
|
||||
|
||||
def pin_contains(self, shape):
|
||||
for pin in self.all_pins:
|
||||
if pin.contains(shape):
|
||||
return True
|
||||
return False
|
||||
|
||||
def convert_point_to_units(self, p):
|
||||
"""
|
||||
Convert a path set of tracks to center line path.
|
||||
|
|
@ -1048,6 +1055,7 @@ class router(router_tech):
|
|||
# Double check source and taget are not same node, if so, we are done!
|
||||
for k, v in self.rg.map.items():
|
||||
if v.source and v.target:
|
||||
self.paths.append([k])
|
||||
return True
|
||||
|
||||
# returns the path in tracks
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ class supply_tree_router(router):
|
|||
"""
|
||||
Route the two nets in a single layer)
|
||||
"""
|
||||
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
||||
debug.info(1, "Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
||||
self.vdd_name = vdd_name
|
||||
self.gnd_name = gnd_name
|
||||
|
||||
# Clear the pins if we have previously routed
|
||||
if (hasattr(self,'rg')):
|
||||
if (hasattr(self, 'rg')):
|
||||
self.clear_pins()
|
||||
else:
|
||||
# Creat a routing grid over the entire area
|
||||
|
|
@ -53,14 +53,14 @@ class supply_tree_router(router):
|
|||
# Get the pin shapes
|
||||
start_time = datetime.now()
|
||||
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
|
||||
print_time("Finding pins and blockages",datetime.now(), start_time, 3)
|
||||
print_time("Finding pins and blockages", datetime.now(), start_time, 3)
|
||||
|
||||
# Route the supply pins to the supply rails
|
||||
# Route vdd first since we want it to be shorter
|
||||
start_time = datetime.now()
|
||||
self.route_pins(vdd_name)
|
||||
self.route_pins(gnd_name)
|
||||
print_time("Maze routing supplies",datetime.now(), start_time, 3)
|
||||
print_time("Maze routing supplies", datetime.now(), start_time, 3)
|
||||
|
||||
# self.write_debug_gds("final_tree_router.gds",False)
|
||||
|
||||
|
|
@ -79,11 +79,11 @@ class supply_tree_router(router):
|
|||
"""
|
||||
|
||||
remaining_components = sum(not x.is_routed() for x in self.pin_groups[pin_name])
|
||||
debug.info(1,"Routing {0} with {1} pin components to connect.".format(pin_name,
|
||||
remaining_components))
|
||||
debug.info(1, "Routing {0} with {1} pin components to connect.".format(pin_name,
|
||||
remaining_components))
|
||||
|
||||
# Create full graph
|
||||
debug.info(2,"Creating adjacency matrix")
|
||||
debug.info(2, "Creating adjacency matrix")
|
||||
pin_size = len(self.pin_groups[pin_name])
|
||||
adj_matrix = [[0] * pin_size for i in range(pin_size)]
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ class supply_tree_router(router):
|
|||
adj_matrix[index1][index2] = dist
|
||||
|
||||
# Find MST
|
||||
debug.info(2,"Finding MinimumSpanning Tree")
|
||||
debug.info(2, "Finding MinimumSpanning Tree")
|
||||
X = csr_matrix(adj_matrix)
|
||||
Tcsr = minimum_spanning_tree(X)
|
||||
mst = Tcsr.toarray().astype(int)
|
||||
|
|
@ -144,6 +144,7 @@ class supply_tree_router(router):
|
|||
self.add_pin_component_source(pin_name, src_idx)
|
||||
|
||||
# Marks all pin components except index as target
|
||||
# which unmarks it as a blockage too
|
||||
self.add_pin_component_target(pin_name, dest_idx)
|
||||
|
||||
# Actually run the A* router
|
||||
|
|
|
|||
|
|
@ -325,13 +325,13 @@ class sram_1bank(sram_base):
|
|||
# they might create some blockages
|
||||
self.add_layout_pins()
|
||||
|
||||
# Route the supplies first since the MST is not blockage aware
|
||||
# and signals can route to anywhere on sides (it is flexible)
|
||||
self.route_supplies()
|
||||
|
||||
# Route the pins to the perimeter
|
||||
if OPTS.perimeter_pins:
|
||||
self.route_escape_pins()
|
||||
|
||||
# Route the supplies first since the MST is not blockage aware
|
||||
# and signals can route to anywhere on sides (it is flexible)
|
||||
self.route_supplies()
|
||||
|
||||
def route_dffs(self, add_routes=True):
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue