From 56f74d32be42103c3524cf0535af99f32cf3ed8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Mon, 12 Oct 2026 22:47:29 +0200 Subject: [PATCH 01/26] test/regfile/riscv32i: the register file's shapes on riscv32i, and an area ledger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit riscv32i's register file inlined, in mode netlist (macro-placed, then dissolved) and in mode macro, on ORFS's own riscv32i config, beside ORFS's riscv32i (flip-flops) to global route. Manual: a study. ledger.tcl accounts for every um2 of the core on any stage's ODB: macros, rows cut beyond the macro boxes, standard cells with the register file's split out, taps, fill and empty row area. On this commit, at 62 %: flops 951 ps, core 4012 um2 inlined 954 ps, core 3544 um2 netlist 954 ps, core 4319 um2; the 996 um2 abstract holds 478 um2 of cells, and the floorplan is sized by the abstract macro MPL-0003 Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- test/regfile/riscv32i/BUILD.bazel | 73 +++++++++++++++++++++++++++ test/regfile/riscv32i/area.tcl | 3 ++ test/regfile/riscv32i/density.tcl | 23 +++++++++ test/regfile/riscv32i/histogram.tcl | 25 +++++++++ test/regfile/riscv32i/inlined.regfile | 18 +++++++ test/regfile/riscv32i/ledger.tcl | 59 ++++++++++++++++++++++ test/regfile/riscv32i/macro.regfile | 18 +++++++ test/regfile/riscv32i/netlist.regfile | 19 +++++++ 8 files changed, 238 insertions(+) create mode 100644 test/regfile/riscv32i/BUILD.bazel create mode 100644 test/regfile/riscv32i/area.tcl create mode 100644 test/regfile/riscv32i/density.tcl create mode 100644 test/regfile/riscv32i/histogram.tcl create mode 100644 test/regfile/riscv32i/inlined.regfile create mode 100644 test/regfile/riscv32i/ledger.tcl create mode 100644 test/regfile/riscv32i/macro.regfile create mode 100644 test/regfile/riscv32i/netlist.regfile diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel new file mode 100644 index 000000000..e6ccbbea8 --- /dev/null +++ b/test/regfile/riscv32i/BUILD.bazel @@ -0,0 +1,73 @@ +load("@orfs_designs//:designs.bzl", "DESIGNS") +load("//:openroad.bzl", "odb_debug", "orfs_flow") + +# riscv32i's register file in each shape generate_regfile offers, on +# ORFS's own riscv32i config (62 %, its io.tcl), to global route: flops +# (ORFS's riscv32i), inlined (synthesis reads the generated netlist), +# netlist (macro-placed, then dissolved) and macro (macro-placed, kept). +# A study, not a gate: every target is manual. +package(default_visibility = ["//visibility:private"]) + +RISCV32I = DESIGNS["asap7/riscv32i"] + +# DESIGNS' labels are ORFS's own, relative to its repository. +SOURCES = { + key: [ + "@orfs" + label if label.startswith("//") else label + for label in labels + ] + for key, labels in RISCV32I["sources"].items() +} + +VERILOG_FILES = [ + "@orfs" + f if f.startswith("//") else f + for f in RISCV32I["verilog_files"] +] + +[ + orfs_flow( + name = "riscv_top", + arguments = RISCV32I["arguments"] | { + "AUTO_MEMORIES": "1", + } | macro_place, + last_stage = "grt", + sources = SOURCES | { + "AUTO_MEMORIES_REGFILES": [":%s.regfile" % shape], + }, + tags = ["manual"], + variant = shape, + verilog_files = VERILOG_FILES, + ) + for shape, macro_place in [ + ("inlined", {}), + ( + "netlist", + {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, + ), + ( + "macro", + {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, + ), + ] +] + +# odb-debug sessions on each stage, for ledger.tcl +# and questions. +[ + odb_debug( + name = "%s_%s_odb_debug" % (shape, stage), + src = src % stage, + tags = ["manual"], + ) + for shape, src in [ + ("flops", "@orfs//flow/designs/asap7/riscv32i:riscv_top_%s"), + ("inlined", ":riscv_top_inlined_%s"), + ("netlist", ":riscv_top_netlist_%s"), + ("macro", ":riscv_top_macro_%s"), + ] + for stage in [ + "synth", + "floorplan", + "grt", + ] +] diff --git a/test/regfile/riscv32i/area.tcl b/test/regfile/riscv32i/area.tcl new file mode 100644 index 000000000..1e08a936b --- /dev/null +++ b/test/regfile/riscv32i/area.tcl @@ -0,0 +1,3 @@ +set b [ord::get_db_block]; set u [$b getDbUnitsPerMicron]; set c [$b getCoreArea]; set a 0 +foreach i [$b getInsts] { set m [$i getMaster]; if {[$m isBlock] || [string match *WELLTAP [$m getType]] || [string match *FILL* [$m getType]]} continue; set a [expr $a+double([$m getWidth])*[$m getHeight]/$u/$u] } +format "core %.0f um2, std cells %.0f um2" [expr double([$c dx])*[$c dy]/$u/$u] $a diff --git a/test/regfile/riscv32i/density.tcl b/test/regfile/riscv32i/density.tcl new file mode 100644 index 000000000..6e3b7502c --- /dev/null +++ b/test/regfile/riscv32i/density.tcl @@ -0,0 +1,23 @@ +set b [ord::get_db_block]; set u [expr double([$b getDbUnitsPerMicron])] +set site 54; set rowh 270 +set x0 1e12; set y0 1e12; set x1 0; set y1 0; set area 0; set tap 0; set n 0 +set kinds [dict create] +set byrow [dict create] +foreach i [$b getInsts] { if {[$i getPlacementStatus] ne "FIRM" || ![string match riscv.dp/rf/* [$i getName]]} continue + set bb [$i getBBox]; set m [$i getMaster]; set a [expr double([expr {[$bb xMax]-[$bb xMin]}])*[expr {[$bb yMax]-[$bb yMin]}]] + set x0 [expr min($x0,[$bb xMin])]; set y0 [expr min($y0,[$bb yMin])]; set x1 [expr max($x1,[$bb xMax])]; set y1 [expr max($y1,[$bb yMax])] + if {[string match *TAP* [$m getName]]} {set tap [expr $tap+$a]} else {set area [expr $area+$a]; incr n} + dict set kinds [$m getName] [expr {[dict exists $kinds [$m getName]] ? [dict get $kinds [$m getName]]+[expr {[$bb xMax]-[$bb xMin]}]/$site : [expr {[$bb xMax]-[$bb xMin]}]/$site}] + dict lappend byrow [$bb yMin] [list [$bb xMin] [$bb xMax]] } +set box [expr double($x1-$x0)*($y1-$y0)] +# gaps per row inside the box +set small 0; set big 0; set nbig 0 +dict for {y l} $byrow { set l [lsort -integer -index 0 $l]; set prev $x0 + foreach e $l { set gap [expr [lindex $e 0]-$prev]; if {$gap > 0} { if {$gap >= 10*$site} {set big [expr $big+$gap]; incr nbig} else {set small [expr $small+$gap]} }; set prev [expr max($prev,[lindex $e 1])] } + set gap [expr $x1-$prev]; if {$gap >= 10*$site} {set big [expr $big+$gap]} else {set small [expr $small+$gap]} } +set rows [dict size $byrow] +set o [format "array box %.1f x %.1f um = %.0f um2, %d rows\n" [expr ($x1-$x0)/$u] [expr ($y1-$y0)/$u] [expr $box/$u/$u] $rows] +append o [format "cells %d: %.0f um2 (%.0f%%), taps %.0f um2 (%.1f%%)\n" $n [expr $area/$u/$u] [expr 100*$area/$box] [expr $tap/$u/$u] [expr 100*$tap/$box]] +append o [format "empty in rows: small gaps (<10 sites, tile slack) %.0f um2 (%.0f%%), wide gaps (>=10 sites: service columns, row ends) %.0f um2 (%.0f%%)\n" [expr $small*$rowh/$u/$u] [expr 100*$small*$rowh/$box] [expr $big*$rowh/$u/$u] [expr 100*$big*$rowh/$box]] +append o "sites per master: [lsort -stride 2 -index 1 -integer -decreasing $kinds]" +set o diff --git a/test/regfile/riscv32i/histogram.tcl b/test/regfile/riscv32i/histogram.tcl new file mode 100644 index 000000000..3cc359db3 --- /dev/null +++ b/test/regfile/riscv32i/histogram.tcl @@ -0,0 +1,25 @@ +set placed [expr {[llength [lsearch -all -inline -not [lmap i [[ord::get_db_block] getInsts] {$i getPlacementStatus}] NONE]] > 0}] +set stage [file rootname [file tail [ord::get_db_block]]] +if {[catch {estimate_parasitics -global_routing} e]} {puts "GRT RC failed: $e"; estimate_parasitics -placement} +set p [get_property [lindex [all_clocks] 0] period] +set w [sta::worst_slack -max] +set paths [find_timing_paths -path_delay max -group_path_count 100000 -endpoint_path_count 1 -sort_by_slack] +set h [dict create]; set n 0; set tns 0 +set groups [dict create] +foreach t $paths { + set s [get_property $t slack]; set ep [get_full_name [get_property $t endpoint]] + if {[regexp {_ff/D$|rf\.rf\[|rf\[} $ep]} {set k rf} elseif {[regexp {/D$} $ep]} {set k reg} else {set k out} + if {$s < 0} {set tns [expr $tns+$s]; dict incr groups $k} + set b [expr {int(floor($s/25.0))*25}] + if {$b > 200} {set b 200} + dict incr h "$b $k" + incr n +} +set o [format "period %.0f WNS %.1f minperiod %.0f TNS %.0f endpoints %d failing %s\n" $p $w [expr $p-$w] $tns $n $groups] +foreach b [lsort -integer -unique [lmap k [dict keys $h] {lindex $k 0}]] { + set r [expr {[dict exists $h "$b rf"] ? [dict get $h "$b rf"] : 0}] + set g [expr {[dict exists $h "$b reg"] ? [dict get $h "$b reg"] : 0}] + set u [expr {[dict exists $h "$b out"] ? [dict get $h "$b out"] : 0}] + append o [format "%6d..%-5s rf %5d otherreg %5d out %4d %s\n" $b [expr {$b==200?"":$b+25}] $r $g $u [string repeat "#" [expr {($r+$g+$u+19)/20}]]] +} +set o diff --git a/test/regfile/riscv32i/inlined.regfile b/test/regfile/riscv32i/inlined.regfile new file mode 100644 index 000000000..eb2130dfd --- /dev/null +++ b/test/regfile/riscv32i/inlined.regfile @@ -0,0 +1,18 @@ +# riscv32i's regfile as a register file of standard cells, inlined in +# synthesis: 32 x 32, two combinational reads, one write through a clock +# gate per word, x0 reads 0 and drops its writes. +module regfile +words 32 +bits 32 +clock clk +read ra1 rd1 +read ra2 rd2 +write wa3 wd3 we3 +zero_word 0 +write_style clock_gate +cell icg ICGx1_ASAP7_75t_R +cell flop DFFHQNx1_ASAP7_75t_R +cell and2 AND2x2_ASAP7_75t_R +cell or2 OR2x2_ASAP7_75t_R +cell ao22 AO22x2_ASAP7_75t_R +cell inv INVx1_ASAP7_75t_R diff --git a/test/regfile/riscv32i/ledger.tcl b/test/regfile/riscv32i/ledger.tcl new file mode 100644 index 000000000..52ef9ca3a --- /dev/null +++ b/test/regfile/riscv32i/ledger.tcl @@ -0,0 +1,59 @@ +# ledger.tcl: where the core goes, on any stage's ODB. Every um2 of the +# core is in exactly one line: macros by master (box, halo ring), core +# not covered by rows (cut around macros, margins), standard cells, +# taps/endcaps, fill, and empty row area. The register file's cells +# (riscv.dp/rf/*) are split out of the standard cells, and their +# bounding box and fill are reported once dissolved. +set b [ord::get_db_block]; set u [expr double([$b getDbUnitsPerMicron])] +proc um2 {a} { return [expr {$a/$::u/$::u}] } +proc boxa {bb} { return [expr {double([$bb xMax]-[$bb xMin])*([$bb yMax]-[$bb yMin])}] } +set c [$b getCoreArea]; set core [boxa $c] +set rows 0; foreach r [$b getRows] { set rows [expr {$rows+[boxa [$r getBBox]]}] } +set macros [dict create]; set std 0; set rf 0; set nrf 0; set tap 0; set fill 0; set unplaced 0 +set rx0 1e18; set ry0 1e18; set rx1 -1e18; set ry1 -1e18; set rfbox 0 +foreach i [$b getInsts] { + set m [$i getMaster]; set a [expr {double([$m getWidth])*[$m getHeight]}] + if {[$m isBlock]} { + set bb [$i getBBox]; set h [$i getHalo]; set ring 0 + if {$h ne "NULL"} { + set ring [expr {double([$bb xMax]-[$bb xMin]+[$h xMin]+[$h xMax])*([$bb yMax]-[$bb yMin]+[$h yMin]+[$h yMax])-$a}] + } + set k [$m getName] + if {![dict exists $macros $k]} { dict set macros $k [list 0 0 0 [$m getWidth] [$m getHeight]] } + lassign [dict get $macros $k] n sa sr w hh + dict set macros $k [list [incr n] [expr {$sa+$a}] [expr {$sr+$ring}] $w $hh] + continue + } + set t [$m getType] + if {[string match *WELLTAP $t] || [string match ENDCAP* $t] || [string match TAP* [$i getName]] || [string match PHY_* [$i getName]]} { set tap [expr {$tap+$a}]; continue } + if {[string match *FILL* [$m getName]] || [string match *DECAP* [$m getName]]} { set fill [expr {$fill+$a}]; continue } + if {![$i isPlaced]} { set unplaced [expr {$unplaced+$a}] } + if {[string match riscv.dp/rf/* [$i getName]]} { + set rf [expr {$rf+$a}]; incr nrf + if {[$i getPlacementStatus] eq "FIRM"} { + set bb [$i getBBox]; set rfbox [expr {$rfbox+$a}] + set rx0 [expr {min($rx0,[$bb xMin])}]; set ry0 [expr {min($ry0,[$bb yMin])}] + set rx1 [expr {max($rx1,[$bb xMax])}]; set ry1 [expr {max($ry1,[$bb yMax])}] + } + continue + } + set std [expr {$std+$a}] +} +set mac 0; set ring 0 +set o [format "core %.0f um2 (%.1f x %.1f um), rows %.0f um2, core without rows %.0f um2\n" [um2 $core] [expr {[$c dx]/$u}] [expr {[$c dy]/$u}] [um2 $rows] [um2 [expr {$core-$rows}]]] +dict for {k v} $macros { + lassign $v n sa sr w hh + set mac [expr {$mac+$sa}]; set ring [expr {$ring+$sr}] + append o [format " macro %-22s x%d %.2f x %.2f um, %.0f um2, halo ring %.0f um2\n" $k $n [expr {$w/$u}] [expr {$hh/$u}] [um2 $sa] [um2 $sr]] +} +append o [format " rows lost beyond the macro boxes (cut halos, margins): %.0f um2\n" [um2 [expr {$core-$rows-$mac}]]] +set pb 0; foreach bl [$b getBlockages] { set pb [expr {$pb+[boxa [$bl getBBox]]}] } +append o [format " placement blockages %.0f um2\n" [um2 $pb]] +append o [format "standard cells %.0f um2 (+ register file %d cells %.0f um2), taps/endcaps %.0f, fill %.0f, unplaced %.0f\n" [um2 $std] $nrf [um2 $rf] [um2 $tap] [um2 $fill] [um2 $unplaced]] +append o [format "empty row area %.0f um2 (rows %.0f%% full)\n" [um2 [expr {$rows-$std-$rf-$tap-$fill}]] [expr {100*($std+$rf+$tap+$fill)/$rows}]] +append o [format "instance area / core = %.1f%% (utilization as initialize_floorplan counts it: macro boxes + cells)\n" [expr {100*($mac+$std+$rf)/$core}]] +if {$rfbox > 0} { + set bx [expr {double($rx1-$rx0)*($ry1-$ry0)}] + append o [format "register file FIRM box %.1f x %.1f um = %.0f um2, its cells %.0f um2 (%.0f%%)\n" [expr {($rx1-$rx0)/$u}] [expr {($ry1-$ry0)/$u}] [um2 $bx] [um2 $rfbox] [expr {100*$rfbox/$bx}]] +} +set o diff --git a/test/regfile/riscv32i/macro.regfile b/test/regfile/riscv32i/macro.regfile new file mode 100644 index 000000000..571ba6b7a --- /dev/null +++ b/test/regfile/riscv32i/macro.regfile @@ -0,0 +1,18 @@ +# riscv32i's regfile, placed as a macro and kept one (mode macro): every +# cell placed by the generator. Otherwise as inlined.regfile. +module regfile +mode macro +words 32 +bits 32 +clock clk +read ra1 rd1 +read ra2 rd2 +write wa3 wd3 we3 +zero_word 0 +write_style clock_gate +cell icg ICGx1_ASAP7_75t_R +cell flop DFFHQNx1_ASAP7_75t_R +cell and2 AND2x2_ASAP7_75t_R +cell or2 OR2x2_ASAP7_75t_R +cell ao22 AO22x2_ASAP7_75t_R +cell inv INVx1_ASAP7_75t_R diff --git a/test/regfile/riscv32i/netlist.regfile b/test/regfile/riscv32i/netlist.regfile new file mode 100644 index 000000000..d8e09216c --- /dev/null +++ b/test/regfile/riscv32i/netlist.regfile @@ -0,0 +1,19 @@ +# riscv32i's regfile, macro-placed and then dissolved (mode netlist): +# its core fixed where the macro was placed, its address decode left to +# the parent. Otherwise as inlined.regfile. +module regfile +mode netlist +words 32 +bits 32 +clock clk +read ra1 rd1 +read ra2 rd2 +write wa3 wd3 we3 +zero_word 0 +write_style clock_gate +cell icg ICGx1_ASAP7_75t_R +cell flop DFFHQNx1_ASAP7_75t_R +cell and2 AND2x2_ASAP7_75t_R +cell or2 OR2x2_ASAP7_75t_R +cell ao22 AO22x2_ASAP7_75t_R +cell inv INVx1_ASAP7_75t_R From 080aa2ec993c9e49093f009dc70eb48082a67706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Mon, 12 Oct 2026 23:44:32 +0200 Subject: [PATCH 02/26] test/regfile/riscv32i: netlist_service0, the register file without service columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit netlist.regfile with service_sites 0: the abstract shrinks from 53.46 x 18.63 to 44.82 x 18.63 um (996 to 835 um2) and the core sized by riscv32i's 62 % from 4319 to 4067 um2, and macro placement fails: MPL-0003, no valid tiling, as in mode macro. The 8 um channels (RTLMP_MIN_CHANNEL_SIZE) around the four FakeRAMs and the register file need more core than the cells do; the larger abstract was what gave the placer its room. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- test/regfile/riscv32i/BUILD.bazel | 5 +++++ .../regfile/riscv32i/netlist_service0.regfile | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/regfile/riscv32i/netlist_service0.regfile diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel index e6ccbbea8..8a3e75a04 100644 --- a/test/regfile/riscv32i/BUILD.bazel +++ b/test/regfile/riscv32i/BUILD.bazel @@ -44,6 +44,10 @@ VERILOG_FILES = [ "netlist", {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, ), + ( + "netlist_service0", + {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, + ), ( "macro", {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, @@ -63,6 +67,7 @@ VERILOG_FILES = [ ("flops", "@orfs//flow/designs/asap7/riscv32i:riscv_top_%s"), ("inlined", ":riscv_top_inlined_%s"), ("netlist", ":riscv_top_netlist_%s"), + ("netlist_service0", ":riscv_top_netlist_service0_%s"), ("macro", ":riscv_top_macro_%s"), ] for stage in [ diff --git a/test/regfile/riscv32i/netlist_service0.regfile b/test/regfile/riscv32i/netlist_service0.regfile new file mode 100644 index 000000000..beb794471 --- /dev/null +++ b/test/regfile/riscv32i/netlist_service0.regfile @@ -0,0 +1,19 @@ +# As netlist.regfile, with no free sites beside the tap columns: the +# parent's clock tree finds its room in the parent's rows. +module regfile +mode netlist +words 32 +bits 32 +clock clk +read ra1 rd1 +read ra2 rd2 +write wa3 wd3 we3 +zero_word 0 +write_style clock_gate +cell icg ICGx1_ASAP7_75t_R +cell flop DFFHQNx1_ASAP7_75t_R +cell and2 AND2x2_ASAP7_75t_R +cell or2 OR2x2_ASAP7_75t_R +cell ao22 AO22x2_ASAP7_75t_R +cell inv INVx1_ASAP7_75t_R +service_sites 0 From 331d5c8c6361e5fa7a10ff1b8dfc68c216f56249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 01:45:53 +0200 Subject: [PATCH 03/26] test/regfile/riscv32i: narrow, every shape with 2 um macro channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit riscv32i's RTLMP_MIN_CHANNEL_SIZE 8 8 is sized for its FakeRAMs; left unset ORFS uses 20 20 and every shape, flops included, fails macro placement. At 2 2, flops, inlined and netlist_service0 reach global route; the core is unchanged (the floorplan is sized by utilization). netlist (the 996 um2 abstract) fails FLW-0004, the register file placed partly outside the core, and macro fails PDN-0233. Minimum period at global route, placement parasitics, 950 ps clock: shape 8 8 2 2 flops 950 ps 992 ps inlined 944 ps 950 ps netlist 953 ps FLW-0004 netlist_service0 MPL-0003 939 ps Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- test/regfile/riscv32i/BUILD.bazel | 40 ++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel index 8a3e75a04..c40515abf 100644 --- a/test/regfile/riscv32i/BUILD.bazel +++ b/test/regfile/riscv32i/BUILD.bazel @@ -24,21 +24,33 @@ VERILOG_FILES = [ for f in RISCV32I["verilog_files"] ] +# riscv32i's RTLMP_MIN_CHANNEL_SIZE (8 8) is sized for its FakeRAMs; +# "narrow" sets 2 2 on every shape, flops included, to measure what the +# channels cost. Left unset, ORFS defaults to 20 20. +NARROW = RISCV32I["arguments"] | {"RTLMP_MIN_CHANNEL_SIZE": "2 2"} + [ orfs_flow( name = "riscv_top", - arguments = RISCV32I["arguments"] | { + arguments = arguments | ({ "AUTO_MEMORIES": "1", - } | macro_place, + } if regfile else {}) | macro_place, last_stage = "grt", - sources = SOURCES | { - "AUTO_MEMORIES_REGFILES": [":%s.regfile" % shape], - }, + sources = SOURCES | ({ + "AUTO_MEMORIES_REGFILES": [":%s.regfile" % regfile], + } if regfile else {}), tags = ["manual"], - variant = shape, + variant = regfile + suffix if regfile else "flops" + suffix, verilog_files = VERILOG_FILES, ) - for shape, macro_place in [ + for suffix, arguments in [ + ( + "", + RISCV32I["arguments"], + ), + ("_narrow", NARROW), + ] + for regfile, macro_place in [ ("inlined", {}), ( "netlist", @@ -52,7 +64,7 @@ VERILOG_FILES = [ "macro", {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, ), - ] + ] + ([("", {})] if suffix else []) ] # odb-debug sessions on each stage, for ledger.tcl @@ -69,6 +81,18 @@ VERILOG_FILES = [ ("netlist", ":riscv_top_netlist_%s"), ("netlist_service0", ":riscv_top_netlist_service0_%s"), ("macro", ":riscv_top_macro_%s"), + ] + [ + ( + shape + "_narrow", + ":riscv_top_%s_narrow_%%s" % shape, + ) + for shape in [ + "flops", + "inlined", + "netlist", + "netlist_service0", + "macro", + ] ] for stage in [ "synth", From 15a89f2148823f0c9c60b0bba6468eeb6af4bdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 06:59:24 +0200 Subject: [PATCH 04/26] regfile: mode netlist's abstract is its core, with a row halo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_regfile (patch 0010), mode netlist: the abstract is the bounding box of the cells it leaves placed, plus one row for a parent of the other row parity, moved to the origin; the header column, the address band and the ring margin were the periphery's or nobody's, and initialize_floorplan -utilization charged them as macro area. No service columns by default in mode netlist (service_sites -1: 40 in a macro, none in netlist), the clock tree's buffers go wherever the parent has room. riscv32i's register file: 53.46 x 18.63 um (996 um2, 48 % cells) to 39.58 x 17.01 um (673 um2, 72 %). macro_place.tcl (patch 0089): each register file in mode netlist gets an instance halo of MACRO_ROWS_HALO_X/Y. The rows are cut that far around the other macros as it dissolves; without the halo the macro placer could set a FakeRAM closer and the cut took the rows under the register file's edge cells (FLW-0014). The padded outline hid this. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- .../0010-openroad-ram-generate-regfile.patch | 108 +++++++++++++++--- .../0089-orfs-auto-memories-regfiles.patch | 31 ++++- 2 files changed, 120 insertions(+), 19 deletions(-) diff --git a/patches/0010-openroad-ram-generate-regfile.patch b/patches/0010-openroad-ram-generate-regfile.patch index 5004c3bf0..6ddb0651b 100644 --- a/patches/0010-openroad-ram-generate-regfile.patch +++ b/patches/0010-openroad-ram-generate-regfile.patch @@ -116,7 +116,7 @@ index 94c5df30369..034eb02a14c 100644 +| Key | Description | +| ---------------------- | -------------------------------------- | +| `module name` | The module and block name. | -+| `mode macro\|netlist` | `macro` (default): the block is a macro to its parent; every cell is placed, the address inverters placed but movable so the macro's own repair can size them. `netlist`: the block is placed as a macro and then dissolves into its parent's cells: the core (storage flops and read bitlines) is fixed where it lies, and the periphery (address inverters, decode, hold) is left unplaced, RAM-0052 says how much, for the parent's placer and resizer, which alone know the drivers and loads outside the array; the abstract's pins sit where their connections land in the array. Which shape is better, and whether the periphery should be unplaced or placed but movable, is still being measured. | ++| `mode macro\|netlist` | `macro` (default): the block is a macro to its parent; every cell is placed, the address inverters placed but movable so the macro's own repair can size them. `netlist`: the block is placed as a macro and then dissolves into its parent's cells: the core (storage flops and read bitlines) is fixed where it lies, and the periphery (address inverters, decode, hold) is left unplaced, RAM-0052 says how much, for the parent's placer and resizer, which alone know the drivers and loads outside the array; the abstract is the core's bounding box, its pins where their connections land in the array. Which shape is better, and whether the periphery should be unplaced or placed but movable, is still being measured. | +| `words n`, `bits n` | Depth and width. | +| `clock port` | The clock port. | +| `reset port` | A reset port the RTL has and the array ignores. | @@ -135,7 +135,7 @@ index 94c5df30369..034eb02a14c 100644 +| `bit_folds n` | The word split into `n` bit bands stacked one above the other. | +| `read_latency 0\|1` | `1` registers each read address on the clock first. | +| `zero_word n` | A word with no storage that reads 0 and drops writes (RISC-V x0). | -+| `tap_columns n`, `service_sites n` | A tap column every `n` bit columns, and free sites beside each for the clock tree. | ++| `tap_columns n`, `service_sites n` | A tap column every `n` bit columns, and free sites beside each for the clock tree: 40 in a macro, none in `mode netlist`, whose clock tree is the parent's. | +| `store_name pattern`, `read_reg_name pattern` | Instance names of the flops, from `{word}`, `{bit}`, `{port}` and `{bank}`. | +| `lib knob value` | The timing model's parameters: `gate_delay_ps`, `wire_factor`, `input_load_ff`, `clock_load_ff`, `leakage_nw_per_cell`, `output_max_cap_ff`, `hold_ps`. | + @@ -254,7 +254,7 @@ new file mode 100644 index 00000000000..fb4b113bda1 --- /dev/null +++ b/src/ram/src/regfile.cpp -@@ -0,0 +1,1642 @@ +@@ -0,0 +1,1712 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + @@ -888,11 +888,16 @@ index 00000000000..fb4b113bda1 + // legal without them; what needs the room is what comes after -- the + // clock tree's buffers and any repair -- and the slack inside a tile + // is a few sites at a time, which a BUFx24 cannot use. Contiguous free -+ // sites next to the flops are where a clock buffer wants to be. ++ // sites next to the flops are where a clock buffer wants to be. In ++ // netlist mode the block dissolves into the parent's rows before the ++ // clock tree, whose buffers go wherever the parent has room: none by ++ // default. ++ const int service_sites ++ = s.service_sites >= 0 ? s.service_sites : (s.mode == "netlist" ? 0 : 40); + const int tap_w = (tap_ ? static_cast(tap_->getWidth()) : 0) -+ + std::max(s.service_sites, 0) * site_w_; ++ + service_sites * site_w_; + const int tap_every = std::max(s.tap_columns, 1); -+ const int tap_cols = (tap_ || s.service_sites > 0) ++ const int tap_cols = (tap_ || service_sites > 0) + ? (bits_per_fold + tap_every - 1) / tap_every + : 0; + // Banks: the word column folded into `banks` columns, `bank_cols` of @@ -1470,8 +1475,11 @@ index 00000000000..fb4b113bda1 + // flow places, sizes and buffers it like any logic: it alone knows the + // drivers and loads outside the array. Fixed by the generator, an + // address inverter drove its literal into every word's decode at a -+ // 3.7 ns slew on XiangShan's ROB that nothing was allowed to repair. The -+ // header column and the address band stay as free sites beside the core. ++ // 3.7 ns slew on XiangShan's ROB that nothing was allowed to repair. ++ // The abstract is then the core's bounding box and no more: the header ++ // column, the address band and the ring margin are the periphery's or ++ // nobody's, and a parent sizing its floorplan by utilization would ++ // charge them as macro area. + // A macro is the generator's to the last cell and keeps its periphery. + if (s.mode == "netlist") { + // The abstract a parent's macro placer sees before the block dissolves @@ -1496,22 +1504,84 @@ index 00000000000..fb4b113bda1 + ++n; + } + if (n > 0) { -+ // on the track grid, as the edge pins are (MPL-0005 otherwise) -+ moves.push_back({t, -+ {on_track(static_cast(sx / n)), -+ on_track(static_cast(sy / n))}}); ++ moves.push_back( ++ {t, {static_cast(sx / n), static_cast(sy / n)}}); + } + } ++ for (dbInst* inst : periphery_insts_) { ++ inst->setPlacementStatus(odb::dbPlacementStatus::UNPLACED); ++ } ++ // The core's bounding box, on the site and row grid as its cells are, ++ // and one row above it becomes the die, its lower left the origin: a ++ // parent whose rows are of the other parity there moves the core up a ++ // row as it dissolves, and the row must be the block's. ++ odb::Rect core; ++ core.mergeInit(); ++ for (dbInst* inst : block_->getInsts()) { ++ if (inst->getPlacementStatus().isPlaced()) { ++ core.merge(inst->getBBox()->getBox()); ++ } ++ } ++ const int dx = core.xMin(); ++ const int dy = core.yMin(); ++ const int first_row = (dy - core_y0_) / row_h_; ++ const int rows = core.dy() / row_h_ + 1; ++ const int box_h = rows * row_h_; ++ for (dbInst* inst : block_->getInsts()) { ++ if (inst->getPlacementStatus().isPlaced()) { ++ const odb::Point at = inst->getLocation(); ++ const odb::dbPlacementStatus status = inst->getPlacementStatus(); ++ // a FIRM cell's origin is fixed (ODB-0359) ++ inst->setPlacementStatus(odb::dbPlacementStatus::PLACED); ++ inst->setLocation(at.x() - dx, at.y() - dy); ++ inst->setPlacementStatus(status); ++ } ++ } ++ std::vector old_rows(block_->getRows().begin(), ++ block_->getRows().end()); ++ for (odb::dbRow* row : old_rows) { ++ odb::dbRow::destroy(row); ++ } ++ for (int r = 0; r < rows; ++r) { ++ std::string rn = "ROW_" + std::to_string(r); ++ odb::dbRow::create(block_, ++ rn.c_str(), ++ site_, ++ 0, ++ r * row_h_, ++ (first_row + r) % 2 == 0 ? odb::dbOrientType::R0 ++ : odb::dbOrientType::MX, ++ odb::dbRowDir::HORIZONTAL, ++ core.dx() / site_w_, ++ site_w_); ++ } ++ block_->setDieArea(odb::Rect(0, 0, core.dx(), box_h)); ++ // Each pin where its connections land, moved with the core and kept ++ // inside it, on the track grid as the edge pins are (MPL-0005 ++ // otherwise). ++ auto inside = [&](int v, int hi) { ++ int t = on_track(std::clamp(v, edge, hi - edge)); ++ while (t > hi - edge && t - track_pitch >= 0) { ++ t -= track_pitch; ++ } ++ return t; ++ }; + for (auto& [t, xy] : moves) { + std::vector old(t->getBPins().begin(), t->getBPins().end()); + for (odb::dbBPin* bp : old) { + odb::dbBPin::destroy(bp); + } -+ Pin(t, layer_h_, xy.first, xy.second); -+ } -+ for (dbInst* inst : periphery_insts_) { -+ inst->setPlacementStatus(odb::dbPlacementStatus::UNPLACED); ++ Pin(t, ++ layer_h_, ++ inside(xy.first - dx, core.dx()), ++ inside(xy.second - dy, box_h)); + } ++ logger_->report( ++ "generate_regfile: mode netlist, the abstract is the core: {} x {} " ++ "um, {} rows", ++ core.dx() / static_cast(tech->getLefUnits()), ++ box_h / static_cast(tech->getLefUnits()), ++ rows); + } + return block_; +} @@ -1902,7 +1972,7 @@ new file mode 100644 index 00000000000..649ac3fe814 --- /dev/null +++ b/src/ram/src/regfile.h -@@ -0,0 +1,182 @@ +@@ -0,0 +1,184 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + @@ -2012,7 +2082,9 @@ index 00000000000..649ac3fe814 + std::vector write; + Cells cells; + int tap_columns = 8; // a tap column every N bit columns -+ int service_sites = 40; // free sites beside each tap, for the clock tree ++ // free sites beside each tap, for the clock tree; -1: 40 in a macro, ++ // none in netlist mode ++ int service_sites = -1; + int banks = 1; // word columns side by side; words % banks == 0 + // How many of the banks stand side by side; the rest stack below them. + // 0 means all of them, one row of banks. The outline is bank_columns diff --git a/patches/0089-orfs-auto-memories-regfiles.patch b/patches/0089-orfs-auto-memories-regfiles.patch index 678a2ad75..fb903ca0f 100644 --- a/patches/0089-orfs-auto-memories-regfiles.patch +++ b/patches/0089-orfs-auto-memories-regfiles.patch @@ -206,7 +206,36 @@ diff --git a/flow/scripts/macro_place.tcl b/flow/scripts/macro_place.tcl index 0789129e4..2fca773e9 100644 --- a/flow/scripts/macro_place.tcl +++ b/flow/scripts/macro_place.tcl -@@ -7,6 +7,9 @@ source $::env(SCRIPTS_DIR)/macro_place_util.tcl +@@ -3,10 +3,38 @@ erase_non_stage_variables floorplan + load_design 2_1_floorplan.odb 2_1_floorplan.sdc + source_step_tcl PRE MACRO_PLACE + ++# A register file in `mode netlist` dissolves onto the parent's rows ++# after macro placement, and the rows are then cut MACRO_ROWS_HALO_X/Y ++# around every other macro: a halo that wide keeps them off its core, ++# which fills its outline to the edge. ++set regfile_list "$::env(RESULTS_DIR)/memories/regfiles.txt" ++if { [env_var_equals AUTO_MEMORIES 1] && [file exists $regfile_list] } { ++ set f [open $regfile_list r] ++ set regfile_masters [split [string trim [read $f]] "\n"] ++ close $f ++ set dbu [[ord::get_db_tech] getDbUnitsPerMicron] ++ set halo {} ++ foreach v {MACRO_ROWS_HALO_X MACRO_ROWS_HALO_Y} { ++ set um [expr { [env_var_exists_and_non_empty $v] ? $::env($v) : 0 }] ++ lappend halo [expr { round($um * $dbu) }] ++ } ++ lassign $halo x y ++ foreach inst [[ord::get_db_block] getInsts] { ++ if { [[$inst getMaster] getName] in $regfile_masters } { ++ # the instance's own halo, left bottom right top, which the macro ++ # placer keeps clear of other macros ++ odb::dbBox_create $inst $x $y $x $y ++ } ++ } ++} ++ + source $::env(SCRIPTS_DIR)/macro_place_util.tcl source_step_tcl POST MACRO_PLACE From 3435b788fc63f61415d4bafc620f38e28dccb08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 06:59:24 +0200 Subject: [PATCH 05/26] test/regfile/riscv32i: netlist at 55 %, where the cropped abstract tiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At riscv32i's 62 % the netlist shape no longer tiles at either channel setting (MPL-0003): the four 42 um tall FakeRAMs and the 17 um register file with its 2 um row halo need 63 um of a 61.6 um core. At 55 %, the utilisation AutoMemories.md measured the padded abstract at (959 ps on 4 644 um2): 938 ps on 4 283 um2, global route, placement parasitics, 950 ps clock. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- test/regfile/riscv32i/BUILD.bazel | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel index c40515abf..252d10abc 100644 --- a/test/regfile/riscv32i/BUILD.bazel +++ b/test/regfile/riscv32i/BUILD.bazel @@ -67,6 +67,25 @@ NARROW = RISCV32I["arguments"] | {"RTLMP_MIN_CHANNEL_SIZE": "2 2"} ] + ([("", {})] if suffix else []) ] +# The netlist shape at 55 %, where AutoMemories.md measured the padded +# abstract (959 ps on a 4 644 um2 core): at 62 % the four 42 um tall +# FakeRAMs and the register file with its row halo do not tile. +orfs_flow( + name = "riscv_top", + arguments = NARROW | { + "AUTO_MEMORIES": "1", + "AUTO_MEMORIES_MACRO_PLACE": "regfile", + "CORE_UTILIZATION": "55", + }, + last_stage = "grt", + sources = SOURCES | { + "AUTO_MEMORIES_REGFILES": [":netlist.regfile"], + }, + tags = ["manual"], + variant = "netlist_narrow_55", + verilog_files = VERILOG_FILES, +) + # odb-debug sessions on each stage, for ledger.tcl # and questions. [ @@ -81,6 +100,7 @@ NARROW = RISCV32I["arguments"] | {"RTLMP_MIN_CHANNEL_SIZE": "2 2"} ("netlist", ":riscv_top_netlist_%s"), ("netlist_service0", ":riscv_top_netlist_service0_%s"), ("macro", ":riscv_top_macro_%s"), + ("netlist_narrow_55", ":riscv_top_netlist_narrow_55_%s"), ] + [ ( shape + "_narrow", From 28229918ba0a7e0f671340a5072d24825fe1bf5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 07:24:26 +0200 Subject: [PATCH 06/26] regfile: generate_regfile's tests read //test's asap7 files, and run here MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch 0010 gave src/ram/test an asap7 symlink to ../../../test/asap7, as Nangate45 and sky130hd are upstream; bazel's patcher does not create symlinks, so the seven generate_regfile tests could not run from this repository (missing input file asap7/...). They now read ../../../test/asap7 and depend on //test:asap7_data and a new //test:asap7_nldm_data, as src/est/test does. test/regfile:openroad_ram_tests runs OpenROAD's ram tests, generate_ram's four and generate_regfile's seven, so CI, which tests this repository's packages and not @openroad's, covers the generator. All eleven pass on the cropped netlist-mode abstract. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- .../0010-openroad-ram-generate-regfile.patch | 53 +++++++++++-------- test/regfile/BUILD.bazel | 20 +++++++ 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/patches/0010-openroad-ram-generate-regfile.patch b/patches/0010-openroad-ram-generate-regfile.patch index 6ddb0651b..e1199ac13 100644 --- a/patches/0010-openroad-ram-generate-regfile.patch +++ b/patches/0010-openroad-ram-generate-regfile.patch @@ -3001,7 +3001,7 @@ diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD index 071fa2c0f0b..9a834644a3e 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD -@@ -13,10 +13,32 @@ COMPULSORY_TESTS = [ +@@ -13,10 +13,27 @@ COMPULSORY_TESTS = [ ] PASSFAIL_TESTS = [ @@ -3020,13 +3020,8 @@ index 071fa2c0f0b..9a834644a3e 100644 +# liberty for constant propagation, the base spec's module. Every test +# but generate_regfile_asap7 (whose own glob has it) adds the spec. +REGFILE_TEST_DATA = [ -+ "asap7/asap7_tech_1x_201209.lef", -+ "asap7/asap7sc7p5t_28_R_1x_220121a.lef", -+ "asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz", -+ "asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz", -+ "asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz", -+ "asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib", -+ "asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz", ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", + "generate_regfile_asap7_rtl.v", + "regfile_checks.tcl", +] @@ -3081,14 +3076,6 @@ index 8545b3dbca9..a02f25bf641 100644 + generate_regfile_write_priority_asap7 ) - -diff --git a/src/ram/test/asap7 b/src/ram/test/asap7 -new file mode 120000 -index 00000000000..16dbc1fd7b7 ---- /dev/null -+++ b/src/ram/test/asap7 -@@ -0,0 +1 @@ -+../../../test/asap7 -\ No newline at end of file diff --git a/src/ram/test/generate_regfile_asap7.regfile b/src/ram/test/generate_regfile_asap7.regfile new file mode 100644 index 00000000000..ad31829371c @@ -3601,13 +3588,13 @@ index 00000000000..56b5ae3ce8a +# generate_regfile tests after helpers.tcl. + +proc rf_read_libraries { } { -+ read_lef asap7/asap7_tech_1x_201209.lef -+ read_lef asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++ read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef + foreach kind { AO OA SIMPLE } { -+ read_liberty asap7/asap7sc7p5t_${kind}_RVT_FF_nldm_211120.lib.gz ++ read_liberty ../../../test/asap7/asap7sc7p5t_${kind}_RVT_FF_nldm_211120.lib.gz + } -+ read_liberty asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz -+ read_liberty asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++ read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++ read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib +} + +# A spec file: the base spec with `lines` appended, in the results dir. @@ -3731,3 +3718,27 @@ index 00000000000..56b5ae3ce8a + } + return $n +} +diff --git a/test/BUILD b/test/BUILD +--- a/test/BUILD ++++ b/test/BUILD +@@ -102,6 +102,20 @@ filegroup( + ], + visibility = ["//visibility:public"], + ) ++ ++# asap7's NLDM liberty, for the cells' functions: generate_regfile's ++# tests read them through OpenSTA's constant propagation. ++filegroup( ++ name = "asap7_nldm_data", ++ srcs = [ ++ "asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz", ++ "asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz", ++ "asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz", ++ "asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib", ++ "asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz", ++ ], ++ visibility = ["//visibility:public"], ++) + + # CCS (current source model) liberty. Required by delay calculators that need + # output current waveforms, e.g. prima; the asap7 libs above are NLDM only. diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 38c5d1cc8..e7d64d6fb 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -157,3 +157,23 @@ build_test( name = "regfile_top_keep_blackboxes_test", targets = [":regfile_top_keep_blackboxes"], ) + +# OpenROAD's own ram tests, generate_ram's and generate_regfile's (patch +# 0010), so a change to the generator runs them here: CI tests this +# repository's packages, not @openroad's. +test_suite( + name = "openroad_ram_tests", + tests = [ + "@openroad//src/ram/test:generate_regfile_asap7-tcl_test", + "@openroad//src/ram/test:generate_regfile_clock_gate_asap7-tcl_test", + "@openroad//src/ram/test:generate_regfile_modes_asap7-tcl_test", + "@openroad//src/ram/test:generate_regfile_reset_asap7-tcl_test", + "@openroad//src/ram/test:generate_regfile_reset_high_asap7-tcl_test", + "@openroad//src/ram/test:generate_regfile_sv_ports_asap7-tcl_test", + "@openroad//src/ram/test:generate_regfile_write_priority_asap7-tcl_test", + "@openroad//src/ram/test:make_7x7_2r1w_nangate45-tcl_test", + "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", + "@openroad//src/ram/test:make_8x8_sky130-tcl_test", + ], +) From 017090c894df095276aabbc79a8fdd9da5c1146b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 07:31:34 +0200 Subject: [PATCH 07/26] regfile: periphery generator|verilog, who builds the periphery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_regfile (patch 0010) gets `periphery generator|verilog`. With `verilog` the periphery (address inverters, decode, write muxes, ties) is written into the netlist as assigns of its cells' functions, for synthesis to map with the parent's logic; the clock gates and the core stay cells. `generator`, the default, is what it built before. Neither dominates: it depends on how the array is integrated, so it is an option. Not yet with mode netlist, whose cells the flow dissolves from the netlist; that needs the core in a module of its own. riscv32i, inlined, global route, placement parasitics, 950 ps clock: periphery channels min period core generator 8 8 944 ps 3544 um2 verilog 8 8 938 ps 3516 um2 generator 2 2 950 ps 3544 um2 verilog 2 2 946 ps 3516 um2 The netlist: 418 assigns for the 403 decode ANDs and 15 address inverters, the 31 clock gates kept. test/regfile/sim simulates it beside riscv32i's RTL as it does the other two write styles. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- .../0010-openroad-ram-generate-regfile.patch | 125 ++++++++++++++++-- test/regfile/riscv32i/BUILD.bazel | 3 + test/regfile/riscv32i/inlined_verilog.regfile | 20 +++ test/regfile/sim/BUILD.bazel | 24 +++- 4 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 test/regfile/riscv32i/inlined_verilog.regfile diff --git a/patches/0010-openroad-ram-generate-regfile.patch b/patches/0010-openroad-ram-generate-regfile.patch index e1199ac13..7f6b4e664 100644 --- a/patches/0010-openroad-ram-generate-regfile.patch +++ b/patches/0010-openroad-ram-generate-regfile.patch @@ -75,7 +75,7 @@ diff --git a/src/ram/README.md b/src/ram/README.md index 94c5df30369..034eb02a14c 100644 --- a/src/ram/README.md +++ b/src/ram/README.md -@@ -80,9 +80,70 @@ generate_ram [-mask_size bits] +@@ -80,9 +80,71 @@ generate_ram [-mask_size bits] | `-use_latch` | If set to `1`, uses a two-phase latch-based design instead of flip-flops for the storage elements. Functionally equivalent to flip-flop design with smaller storage cell area. Default: `0`. | | `-write_behavioral_verilog` | Write a behavioral Verilog model of the RAM array to the specified file. | @@ -135,6 +135,7 @@ index 94c5df30369..034eb02a14c 100644 +| `bit_folds n` | The word split into `n` bit bands stacked one above the other. | +| `read_latency 0\|1` | `1` registers each read address on the clock first. | +| `zero_word n` | A word with no storage that reads 0 and drops writes (RISC-V x0). | ++| `periphery generator\|verilog` | Who builds the periphery (address inverters, decode, write muxes, hold): `generator` (the default), as cells placed with the array or, in `mode netlist`, left to the parent; `verilog`, as assigns of those cells' functions in the netlist, for synthesis to map with the parent's logic, the clock gates kept as cells. Which is better depends on how the array is integrated. Not yet with `mode netlist`, whose cells the flow dissolves. | +| `tap_columns n`, `service_sites n` | A tap column every `n` bit columns, and free sites beside each for the clock tree: 40 in a macro, none in `mode netlist`, whose clock tree is the parent's. | +| `store_name pattern`, `read_reg_name pattern` | Instance names of the flops, from `{word}`, `{bit}`, `{port}` and `{bank}`. | +| `lib knob value` | The timing model's parameters: `gate_delay_ps`, `wire_factor`, `input_load_ff`, `clock_load_ff`, `leakage_nw_per_cell`, `output_max_cap_ff`, `hold_ps`. | @@ -254,7 +255,7 @@ new file mode 100644 index 00000000000..fb4b113bda1 --- /dev/null +++ b/src/ram/src/regfile.cpp -@@ -0,0 +1,1712 @@ +@@ -0,0 +1,1810 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + @@ -263,6 +264,7 @@ index 00000000000..fb4b113bda1 +#include "regfile.h" + +#include ++#include +#include +#include +#include @@ -1583,6 +1585,13 @@ index 00000000000..fb4b113bda1 + box_h / static_cast(tech->getLefUnits()), + rows); + } ++ if (s.periphery == "verilog") { ++ // synthesis maps the periphery from its assigns; the cells here are ++ // only its description ++ for (dbInst* inst : periphery_insts_) { ++ inst->setPlacementStatus(odb::dbPlacementStatus::UNPLACED); ++ } ++ } + return block_; +} + @@ -1629,6 +1638,13 @@ index 00000000000..fb4b113bda1 + + ": mode is macro or netlist, not `" + v[0] + "`"); + } + s.mode = v[0]; ++ } else if (key == "periphery") { ++ need(1); ++ if (v[0] != "generator" && v[0] != "verilog") { ++ Refuse(path + ":" + std::to_string(lineno) ++ + ": periphery is generator or verilog, not `" + v[0] + "`"); ++ } ++ s.periphery = v[0]; + } else if (key == "words") { + need(1); + s.words = std::stoi(v[0]); @@ -1867,6 +1883,12 @@ index 00000000000..fb4b113bda1 + if (s.module.empty()) { + Refuse(path + ": no `module`"); + } ++ if (s.periphery == "verilog" && s.mode == "netlist") { ++ // the flow dissolves the netlist's cells; assigns need a module of ++ // their own around the core, which it does not split out yet ++ Refuse(path + ": `periphery verilog` with `mode netlist` is not " ++ "supported yet"); ++ } + if (s.cells.flop.empty() || s.cells.and2.empty() || s.cells.or2.empty() + || s.cells.ao22.empty() || s.cells.inv.empty()) { + Refuse(path + ": cells flop, and2, or2, ao22 and inv are all required"); @@ -1885,8 +1907,51 @@ index 00000000000..fb4b113bda1 + return b.Run(); +} + -+void WriteVerilog(odb::dbBlock* block, const std::string& path) ++void WriteVerilog(odb::dbBlock* block, ++ const std::string& path, ++ const Spec& spec) +{ ++ // With `periphery verilog`, each unplaced logic cell of the periphery ++ // as an assign of its function: output pin, and the expression over ++ // its input pins, `@PIN` standing for the pin's net. ++ struct Function ++ { ++ std::string out; ++ std::string expr; ++ }; ++ std::map functions; ++ if (spec.periphery == "verilog") { ++ const Pins& p = g_pins; ++ auto add = [&](const std::string& master, const Function& f) { ++ if (master.empty()) { ++ return; ++ } ++ auto [it, fresh] = functions.emplace(master, f); ++ if (!fresh && it->second.expr != f.expr) { ++ Refuse("cell " + master + " serves two roles with different " ++ "functions; `periphery verilog` needs one per cell"); ++ } ++ }; ++ auto pin = [](const std::string& n) { return "@" + n; }; ++ add(spec.cells.and2, ++ {p.and2[2], pin(p.and2[0]) + " & " + pin(p.and2[1])}); ++ add(spec.cells.or2, {p.or2[2], pin(p.or2[0]) + " | " + pin(p.or2[1])}); ++ add(spec.cells.nand2, ++ {p.nand2[2], "~(" + pin(p.nand2[0]) + " & " + pin(p.nand2[1]) + ")"}); ++ add(spec.cells.nor2, ++ {p.nor2[2], "~(" + pin(p.nor2[0]) + " | " + pin(p.nor2[1]) + ")"}); ++ add(spec.cells.inv, {p.inv[1], "~" + pin(p.inv[0])}); ++ add(spec.cells.ao22, ++ {p.ao22[4], ++ "(" + pin(p.ao22[0]) + " & " + pin(p.ao22[1]) + ") | (" ++ + pin(p.ao22[2]) + " & " + pin(p.ao22[3]) + ")"}); ++ add(spec.cells.aoi22, ++ {p.aoi22[4], ++ "~((" + pin(p.aoi22[0]) + " & " + pin(p.aoi22[1]) + ") | (" ++ + pin(p.aoi22[2]) + " & " + pin(p.aoi22[3]) + "))"}); ++ add(spec.cells.tie_hi, {p.tie_hi[0], "1'b1"}); ++ add(spec.cells.tie_lo, {p.tie_lo[0], "1'b0"}); ++ } + std::ofstream out(path); + if (!out) { + Refuse("cannot write " + path); @@ -1919,7 +1984,8 @@ index 00000000000..fb4b113bda1 + } + it->second.hi = std::max(it->second.hi, idx); + } -+ out << "// Generated by generate_regfile. Structural: every cell placed.\n"; ++ out << "// Generated by generate_regfile. Structural" ++ << (functions.empty() ? "" : ", the periphery as assigns") << ".\n"; + out << "module " << block->getName() << "(\n"; + for (size_t i = 0; i < order.size(); ++i) { + const Bus& b = buses[order[i]]; @@ -1940,7 +2006,40 @@ index 00000000000..fb4b113bda1 + } + out << " wire \\" << n->getName() << " ;\n"; + } ++ // A port net by its port name, buses with [i] intact; any other net ++ // escaped. ++ auto ref = [](odb::dbNet* n) { ++ return n->getBTerms().begin() != n->getBTerms().end() ++ ? n->getName() ++ : "\\" + n->getName() + " "; ++ }; + for (odb::dbInst* inst : block->getInsts()) { ++ auto f = functions.find(inst->getMaster()->getName()); ++ if (f != functions.end() && !inst->getPlacementStatus().isPlaced()) { ++ odb::dbITerm* y = inst->findITerm(f->second.out.c_str()); ++ if (y == nullptr || y->getNet() == nullptr) { ++ continue; // drives nothing ++ } ++ std::string expr = f->second.expr; ++ for (size_t at = expr.find('@'); at != std::string::npos; ++ at = expr.find('@', at)) { ++ size_t end = at + 1; ++ while (end < expr.size() ++ && (std::isalnum(static_cast(expr[end])) ++ || expr[end] == '_')) { ++ ++end; ++ } ++ odb::dbITerm* in = inst->findITerm(expr.substr(at + 1, end - at - 1).c_str()); ++ const std::string r = in != nullptr && in->getNet() != nullptr ++ ? ref(in->getNet()) ++ : "1'b0"; ++ expr.replace(at, end - at, r); ++ at += r.size(); ++ } ++ out << " assign " << ref(y->getNet()) << " = " << expr << "; // " ++ << inst->getName() << "\n"; ++ continue; ++ } + out << " " << inst->getMaster()->getName() << " \\" << inst->getName() + << " ("; + bool first = true; @@ -1972,7 +2071,7 @@ new file mode 100644 index 00000000000..649ac3fe814 --- /dev/null +++ b/src/ram/src/regfile.h -@@ -0,0 +1,184 @@ +@@ -0,0 +1,194 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + @@ -2063,6 +2162,13 @@ index 00000000000..649ac3fe814 + // flow); the generator builds the same block either way. The flow's + // memories step reads this key too, and decides which views to ask for. + std::string mode = "macro"; ++ // Who builds the periphery -- address inverters, decode, write muxes, ++ // hold: "generator" (cells, placed with the array or, in mode netlist, ++ // left unplaced for the parent) or "verilog" (written as assigns of ++ // the cells' functions, for synthesis to map with the parent's logic; ++ // the clock gates stay cells). Neither dominates: it depends on how ++ // the array is integrated. ++ std::string periphery = "generator"; + std::string module; // generated module and block name + int words = 0; + int bits = 0; @@ -2153,8 +2259,11 @@ index 00000000000..649ac3fe814 + const Spec& spec); + +// Writes the block as a structural Verilog module, cells as instances, -+// for simulation and for the flow's netlist view. -+void WriteVerilog(odb::dbBlock* block, const std::string& path); ++// for simulation and for the flow's netlist view; with `periphery ++// verilog`, the unplaced periphery's logic cells as assigns. ++void WriteVerilog(odb::dbBlock* block, ++ const std::string& path, ++ const Spec& spec); + +} // namespace ram::regfile diff --git a/src/ram/src/regfile_cmd.cpp b/src/ram/src/regfile_cmd.cpp @@ -2228,7 +2337,7 @@ index 00000000000..d90332ba559 + fixed); + } + if (!verilog_path.empty()) { -+ regfile::WriteVerilog(block, verilog_path); ++ regfile::WriteVerilog(block, verilog_path, spec); + } + if (!def_path.empty()) { + odb::DefOut writer(logger); diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel index 252d10abc..914c21db3 100644 --- a/test/regfile/riscv32i/BUILD.bazel +++ b/test/regfile/riscv32i/BUILD.bazel @@ -52,6 +52,7 @@ NARROW = RISCV32I["arguments"] | {"RTLMP_MIN_CHANNEL_SIZE": "2 2"} ] for regfile, macro_place in [ ("inlined", {}), + ("inlined_verilog", {}), ( "netlist", {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, @@ -97,6 +98,7 @@ orfs_flow( for shape, src in [ ("flops", "@orfs//flow/designs/asap7/riscv32i:riscv_top_%s"), ("inlined", ":riscv_top_inlined_%s"), + ("inlined_verilog", ":riscv_top_inlined_verilog_%s"), ("netlist", ":riscv_top_netlist_%s"), ("netlist_service0", ":riscv_top_netlist_service0_%s"), ("macro", ":riscv_top_macro_%s"), @@ -109,6 +111,7 @@ orfs_flow( for shape in [ "flops", "inlined", + "inlined_verilog", "netlist", "netlist_service0", "macro", diff --git a/test/regfile/riscv32i/inlined_verilog.regfile b/test/regfile/riscv32i/inlined_verilog.regfile new file mode 100644 index 000000000..dcb905515 --- /dev/null +++ b/test/regfile/riscv32i/inlined_verilog.regfile @@ -0,0 +1,20 @@ +# riscv32i's regfile as a register file of standard cells, inlined in +# synthesis: 32 x 32, two combinational reads, one write through a clock +# gate per word, x0 reads 0 and drops its writes. The periphery +# (address inverters, decode) as assigns for synthesis to map. +module regfile +words 32 +bits 32 +clock clk +read ra1 rd1 +read ra2 rd2 +write wa3 wd3 we3 +zero_word 0 +write_style clock_gate +cell icg ICGx1_ASAP7_75t_R +cell flop DFFHQNx1_ASAP7_75t_R +cell and2 AND2x2_ASAP7_75t_R +cell or2 OR2x2_ASAP7_75t_R +cell ao22 AO22x2_ASAP7_75t_R +cell inv INVx1_ASAP7_75t_R +periphery verilog diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index e3590a5f6..7056d025d 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -2,7 +2,8 @@ # riscv32i's register file as generate_regfile writes it, simulated beside # src/riscv32i/regfile.v under random reads and writes, every read # compared. One netlist per write style: a hold mux per bit, and a clock -# gate per word. +# gate per word; and the clock gate with its periphery as assigns +# (`periphery verilog`). load("@rules_cc//cc:defs.bzl", "cc_test") load("@rules_verilator//verilator:defs.bzl", "verilator_cc_library") load("@rules_verilog//verilog:defs.bzl", "verilog_library") @@ -44,7 +45,10 @@ TCL $(location @openroad//:openroad) -exit -no_init -no_splash $(@D)/regfile_{style}.tcl > $(@D)/regfile_{style}.log 2>&1 || {{ cat $(@D)/regfile_{style}.log; exit 1; }} sed 's/^module regfile(/module regfile_gen(/' $(@D)/regfile_{style}.gen.v > $@ """.format( - extra = "echo 'write_style clock_gate' >> $(@D)/regfile_%s.regfile" % style if style == "clock_gate" else "", + extra = "\n".join([ + "echo '%s' >> $(@D)/regfile_%s.regfile" % (line, style) + for line in lines + ]), style = style, ), tools = ["@openroad"], @@ -77,8 +81,18 @@ sed 's/^module regfile(/module regfile_gen(/' $(@D)/regfile_{style}.gen.v > $@ deps = [":tb_%s" % style], ), ] - for style in [ - "mux", - "clock_gate", + for style, lines in [ + ("mux", []), + ( + "clock_gate", + ["write_style clock_gate"], + ), + ( + "clock_gate_verilog", + [ + "write_style clock_gate", + "periphery verilog", + ], + ), ] ] From 80f96a6eb555e5a394f6fc9ec22ab5b93270a79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 07:42:53 +0200 Subject: [PATCH 08/26] regfile: periphery verilog in mode netlist, the core a macro of its own MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_regfile (patch 0010): with `periphery verilog` and `mode netlist` the block is the core alone, _core. The periphery leaves it for a wrapper module in the RTL module's place: the periphery as assigns, the clock gates as cells, around an instance of the core declared a blackbox. A net the core shares with the periphery becomes a core port; a module port only the periphery uses leaves the core. The LEF, DEF and a liberty of area and pins describe the core; -verilog writes the wrapper and _core.v the core's netlist. ORFS patch 0108: gen_memories inlines the wrapper (inline.txt) and makes the core the macro: blackboxes.txt, regfiles.txt, its .lef, .lib and .place, so it is macro-placed with its halo and dissolves. test/regfile/sim simulates the wrapper and core beside riscv32i's RTL. riscv32i at 55 %, global route, placement parasitics, 950 ps clock: 940 ps on 4 287 um2, the generator's periphery 938 ps on 4 283 um2. The ledger matches riscv.dp.rf/*, the wrapper flattened by synthesis. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- orfs_source.bzl | 5 + .../0010-openroad-ram-generate-regfile.patch | 482 +++++++++++++++--- .../0108-orfs-regfile-periphery-verilog.patch | 70 +++ test/regfile/riscv32i/BUILD.bazel | 41 +- test/regfile/riscv32i/ledger.tcl | 5 +- test/regfile/riscv32i/netlist_verilog.regfile | 22 + test/regfile/sim/BUILD.bazel | 20 +- 7 files changed, 551 insertions(+), 94 deletions(-) create mode 100644 patches/0108-orfs-regfile-periphery-verilog.patch create mode 100644 test/regfile/riscv32i/netlist_verilog.regfile diff --git a/orfs_source.bzl b/orfs_source.bzl index 30ebfba5d..e4561d968 100644 --- a/orfs_source.bzl +++ b/orfs_source.bzl @@ -159,6 +159,11 @@ ORFS_PATCHES = [ # for a fresh snapshot of coralnpu; and the coralnpu README. Needs # 0103. Label("//patches:0106-orfs-coralnpu-exmem.patch"), + # 0108: a register file with `periphery verilog` in mode netlist: its + # core the macro, _core, and a wrapper of the periphery read + # in the module's place. On 0089 and 0091; retires with 0089. Not + # upstreamed. + Label("//patches:0108-orfs-regfile-periphery-verilog.patch"), ] # Generate the BUILD file for any design directory that has a config.mk diff --git a/patches/0010-openroad-ram-generate-regfile.patch b/patches/0010-openroad-ram-generate-regfile.patch index 7f6b4e664..abdf7254b 100644 --- a/patches/0010-openroad-ram-generate-regfile.patch +++ b/patches/0010-openroad-ram-generate-regfile.patch @@ -135,7 +135,7 @@ index 94c5df30369..034eb02a14c 100644 +| `bit_folds n` | The word split into `n` bit bands stacked one above the other. | +| `read_latency 0\|1` | `1` registers each read address on the clock first. | +| `zero_word n` | A word with no storage that reads 0 and drops writes (RISC-V x0). | -+| `periphery generator\|verilog` | Who builds the periphery (address inverters, decode, write muxes, hold): `generator` (the default), as cells placed with the array or, in `mode netlist`, left to the parent; `verilog`, as assigns of those cells' functions in the netlist, for synthesis to map with the parent's logic, the clock gates kept as cells. Which is better depends on how the array is integrated. Not yet with `mode netlist`, whose cells the flow dissolves. | ++| `periphery generator\|verilog` | Who builds the periphery (address inverters, decode, write muxes, hold): `generator` (the default), as cells placed with the array or, in `mode netlist`, left to the parent; `verilog`, as assigns of those cells' functions in the netlist, for synthesis to map with the parent's logic, the clock gates kept as cells. Which is better depends on how the array is integrated. With `mode netlist` the block is the core alone, `_core`, its ports the nets it shares with the periphery: `-lef`, `-liberty` and `-def` describe it, `-verilog` writes the wrapper module, the periphery around an instance of the core declared a blackbox, and `_core.v` beside it the core's netlist. | +| `tap_columns n`, `service_sites n` | A tap column every `n` bit columns, and free sites beside each for the clock tree: 40 in a macro, none in `mode netlist`, whose clock tree is the parent's. | +| `store_name pattern`, `read_reg_name pattern` | Instance names of the flops, from `{word}`, `{bit}`, `{port}` and `{bank}`. | +| `lib knob value` | The timing model's parameters: `gate_delay_ps`, `wire_factor`, `input_load_ff`, `clock_load_ff`, `leakage_nw_per_cell`, `output_max_cap_ff`, `hold_ps`. | @@ -255,7 +255,7 @@ new file mode 100644 index 00000000000..fb4b113bda1 --- /dev/null +++ b/src/ram/src/regfile.cpp -@@ -0,0 +1,1810 @@ +@@ -0,0 +1,2054 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + @@ -269,6 +269,7 @@ index 00000000000..fb4b113bda1 +#include +#include +#include ++#include +#include +#include +#include @@ -344,6 +345,32 @@ index 00000000000..fb4b113bda1 + +Pins g_pins; // set by ReadSpec, read by Generate + ++// `periphery verilog` with `mode netlist`: the block is the core alone, ++// _core, its ports the module's ports it uses and the nets it ++// shares with the periphery; the periphery is a wrapper module around it, ++// written by WriteVerilog. Generate fills this, WriteVerilog reads it. ++struct WrapperCell ++{ ++ std::string master; ++ std::string name; ++ std::vector> conns; // pin, net ++}; ++struct Wrapper ++{ ++ std::string module; // the RTL module the wrapper stands in for ++ std::string core; // the block: _core ++ std::vector> ports; // the module's ++ std::vector wires; // its nets that are not ports ++ std::vector cells; // the periphery ++ std::vector> core_conns; // port, net ++}; ++Wrapper g_wrapper; ++ ++bool SplitPeriphery(const Spec& s) ++{ ++ return s.periphery == "verilog" && s.mode == "netlist"; ++} ++ +// Everything the builder needs while it lays cells into rows. +class Builder +{ @@ -587,6 +614,105 @@ index 00000000000..fb4b113bda1 + bp->setPlacementStatus(odb::dbPlacementStatus::FIRM); + } + ++ // `periphery verilog` with `mode netlist`: the periphery leaves the ++ // block for the wrapper module (g_wrapper); a net it shares with the ++ // core becomes a port of the core, an input where the periphery drives ++ // it, an output where the core does. A module port only the periphery ++ // uses leaves the core. ++ void SplitCore() ++ { ++ std::set periphery; // by id: odb objects have no order ++ for (dbInst* inst : periphery_insts_) { ++ periphery.insert(inst->getId()); ++ } ++ auto ref = [](dbNet* n) { ++ return n->getBTerms().begin() != n->getBTerms().end() ++ ? std::string((*n->getBTerms().begin())->getName()) ++ : "\\" + n->getName() + " "; ++ }; ++ g_wrapper.module = spec_.module; ++ g_wrapper.core = block_->getName(); ++ for (odb::dbBTerm* t : block_->getBTerms()) { ++ g_wrapper.ports.emplace_back(t->getName(), t->getIoType()); ++ } ++ std::vector dropped; ++ std::vector> shared; ++ for (dbNet* n : block_->getNets()) { ++ if (n->getSigType() == odb::dbSigType::POWER ++ || n->getSigType() == odb::dbSigType::GROUND) { ++ continue; ++ } ++ bool in_periphery = false; ++ bool in_core = false; ++ bool periphery_drives = false; ++ for (odb::dbITerm* it : n->getITerms()) { ++ const bool p = periphery.count(it->getInst()->getId()) > 0; ++ in_periphery |= p; ++ in_core |= !p; ++ if (p && it->getIoType() == odb::dbIoType::OUTPUT) { ++ periphery_drives = true; ++ } ++ } ++ const bool port = n->getBTerms().begin() != n->getBTerms().end(); ++ if (port) { ++ if (in_core) { ++ const std::string name = (*n->getBTerms().begin())->getName(); ++ g_wrapper.core_conns.emplace_back(name, name); ++ } else { ++ for (odb::dbBTerm* t : n->getBTerms()) { ++ dropped.push_back(t); ++ } ++ } ++ continue; ++ } ++ if (in_periphery) { ++ g_wrapper.wires.push_back(ref(n)); ++ } ++ if (in_periphery && in_core) { ++ shared.emplace_back(n, periphery_drives ? odb::dbIoType::INPUT ++ : odb::dbIoType::OUTPUT); ++ } ++ } ++ for (dbInst* inst : periphery_insts_) { ++ WrapperCell cell{inst->getMaster()->getName(), inst->getName(), {}}; ++ for (odb::dbITerm* it : inst->getITerms()) { ++ if (it->getNet() != nullptr ++ && it->getNet()->getSigType() != odb::dbSigType::POWER ++ && it->getNet()->getSigType() != odb::dbSigType::GROUND) { ++ cell.conns.emplace_back(it->getMTerm()->getName(), ref(it->getNet())); ++ } ++ } ++ g_wrapper.cells.push_back(std::move(cell)); ++ } ++ for (auto& [n, io] : shared) { ++ dbBTerm* t = dbBTerm::create(n, n->getName().c_str()); ++ t->setIoType(io); ++ t->setSigType(odb::dbSigType::SIGNAL); ++ g_wrapper.core_conns.emplace_back(n->getName(), ref(n)); ++ } ++ for (odb::dbBTerm* t : dropped) { ++ std::vector pins(t->getBPins().begin(), ++ t->getBPins().end()); ++ for (odb::dbBPin* bp : pins) { ++ odb::dbBPin::destroy(bp); ++ } ++ odb::dbBTerm::destroy(t); ++ } ++ for (dbInst* inst : periphery_insts_) { ++ dbInst::destroy(inst); ++ } ++ periphery_insts_.clear(); ++ std::vector empty; ++ for (dbNet* n : block_->getNets()) { ++ if (n->getITerms().empty() && n->getBTerms().empty()) { ++ empty.push_back(n); ++ } ++ } ++ for (dbNet* n : empty) { ++ dbNet::destroy(n); ++ } ++ } ++ + odb::dbDatabase* db_; + utl::Logger* logger_; + const Spec& spec_; @@ -693,7 +819,10 @@ index 00000000000..fb4b113bda1 + Refuse("the database already has a top block (" + + chip->getBlock()->getName() + "); one generation per database"); + } -+ block_ = dbBlock::create(chip, s.module.c_str()); ++ g_wrapper = Wrapper{}; ++ const std::string block_name ++ = SplitPeriphery(s) ? s.module + "_core" : s.module; ++ block_ = dbBlock::create(chip, block_name.c_str()); + if (block_ == nullptr) { + Refuse("could not create block " + s.module); + } @@ -1483,6 +1612,9 @@ index 00000000000..fb4b113bda1 + // nobody's, and a parent sizing its floorplan by utilization would + // charge them as macro area. + // A macro is the generator's to the last cell and keeps its periphery. ++ if (SplitPeriphery(s)) { ++ SplitCore(); ++ } + if (s.mode == "netlist") { + // The abstract a parent's macro placer sees before the block dissolves + // into its rows: each port's pin where its connections land, at the @@ -1883,12 +2015,6 @@ index 00000000000..fb4b113bda1 + if (s.module.empty()) { + Refuse(path + ": no `module`"); + } -+ if (s.periphery == "verilog" && s.mode == "netlist") { -+ // the flow dissolves the netlist's cells; assigns need a module of -+ // their own around the core, which it does not split out yet -+ Refuse(path + ": `periphery verilog` with `mode netlist` is not " -+ "supported yet"); -+ } + if (s.cells.flop.empty() || s.cells.and2.empty() || s.cells.or2.empty() + || s.cells.ao22.empty() || s.cells.inv.empty()) { + Refuse(path + ": cells flop, and2, or2, ao22 and inv are all required"); @@ -1907,18 +2033,17 @@ index 00000000000..fb4b113bda1 + return b.Run(); +} + -+void WriteVerilog(odb::dbBlock* block, -+ const std::string& path, -+ const Spec& spec) ++// With `periphery verilog`, each unplaced logic cell of the periphery ++// as an assign of its function: output pin, and the expression over ++// its input pins, `@PIN` standing for the pin's net. ++struct Function ++{ ++ std::string out; ++ std::string expr; ++}; ++ ++static std::map PeripheryFunctions(const Spec& spec) +{ -+ // With `periphery verilog`, each unplaced logic cell of the periphery -+ // as an assign of its function: output pin, and the expression over -+ // its input pins, `@PIN` standing for the pin's net. -+ struct Function -+ { -+ std::string out; -+ std::string expr; -+ }; + std::map functions; + if (spec.periphery == "verilog") { + const Pins& p = g_pins; @@ -1952,24 +2077,52 @@ index 00000000000..fb4b113bda1 + add(spec.cells.tie_hi, {p.tie_hi[0], "1'b1"}); + add(spec.cells.tie_lo, {p.tie_lo[0], "1'b0"}); + } -+ std::ofstream out(path); -+ if (!out) { -+ Refuse("cannot write " + path); -+ } -+ // Group bterms into buses by `name[i]`. -+ struct Bus -+ { -+ odb::dbIoType io; -+ int hi = -1; -+ bool scalar = false; -+ }; -+ std::map buses; -+ std::vector order; -+ for (odb::dbBTerm* t : block->getBTerms()) { -+ std::string n = t->getName(); -+ if (t->getSigType() != odb::dbSigType::SIGNAL) { -+ continue; ++ return functions; ++} ++ ++// A port net by its port name, buses with [i] intact; any other net ++// escaped. ++static std::string NetRef(odb::dbNet* n) ++{ ++ return n->getBTerms().begin() != n->getBTerms().end() ++ ? n->getName() ++ : "\\" + n->getName() + " "; ++} ++ ++// An assign of `f` for `inst`, its pins by their nets as `net` names them. ++static std::string Assign(const Function& f, ++ const std::string& name, ++ const std::function& net) ++{ ++ std::string expr = f.expr; ++ for (size_t at = expr.find('@'); at != std::string::npos; ++ at = expr.find('@', at)) { ++ size_t end = at + 1; ++ while (end < expr.size() ++ && (std::isalnum(static_cast(expr[end])) ++ || expr[end] == '_')) { ++ ++end; + } ++ const std::string r = net(expr.substr(at + 1, end - at - 1)); ++ expr.replace(at, end - at, r.empty() ? "1'b0" : r); ++ at += r.empty() ? 4 : r.size(); ++ } ++ return " assign " + net(f.out) + " = " + expr + "; // " + name + "\n"; ++} ++ ++// The block's ports grouped into buses by `name[i]`, in order. ++struct Bus ++{ ++ odb::dbIoType io; ++ int hi = -1; ++ bool scalar = false; ++}; ++static std::vector> Buses( ++ const std::vector>& ports) ++{ ++ std::map at; ++ std::vector> buses; ++ for (const auto& [n, io] : ports) { + auto lb = n.rfind('['); + std::string base = n; + int idx = -1; @@ -1977,25 +2130,56 @@ index 00000000000..fb4b113bda1 + base = n.substr(0, lb); + idx = std::stoi(n.substr(lb + 1, n.size() - lb - 2)); + } -+ auto it = buses.find(base); -+ if (it == buses.end()) { -+ order.push_back(base); -+ it = buses.emplace(base, Bus{t->getIoType(), -1, idx < 0}).first; ++ auto it = at.find(base); ++ if (it == at.end()) { ++ it = at.emplace(base, buses.size()).first; ++ buses.push_back({base, Bus{io, -1, idx < 0}}); + } -+ it->second.hi = std::max(it->second.hi, idx); ++ buses[it->second].second.hi = std::max(buses[it->second].second.hi, idx); + } -+ out << "// Generated by generate_regfile. Structural" -+ << (functions.empty() ? "" : ", the periphery as assigns") << ".\n"; -+ out << "module " << block->getName() << "(\n"; -+ for (size_t i = 0; i < order.size(); ++i) { -+ const Bus& b = buses[order[i]]; ++ return buses; ++} ++ ++static std::vector> Ports( ++ odb::dbBlock* block) ++{ ++ std::vector> ports; ++ for (odb::dbBTerm* t : block->getBTerms()) { ++ if (t->getSigType() == odb::dbSigType::SIGNAL) { ++ ports.emplace_back(t->getName(), t->getIoType()); ++ } ++ } ++ return ports; ++} ++ ++static void Header(std::ostream& out, ++ const std::string& module, ++ const std::vector>& buses) ++{ ++ out << "module " << module << "(\n"; ++ for (size_t i = 0; i < buses.size(); ++i) { ++ const Bus& b = buses[i].second; + out << " " << (b.io == odb::dbIoType::INPUT ? "input" : "output"); + if (!b.scalar) { + out << " [" << b.hi << ":0]"; + } -+ out << " " << order[i] << (i + 1 < order.size() ? ",\n" : "\n"); ++ out << " " << buses[i].first << (i + 1 < buses.size() ? ",\n" : "\n"); + } + out << ");\n"; ++} ++ ++static void WriteStructural(odb::dbBlock* block, ++ const std::string& path, ++ const Spec& spec) ++{ ++ const std::map functions = PeripheryFunctions(spec); ++ std::ofstream out(path); ++ if (!out) { ++ Refuse("cannot write " + path); ++ } ++ out << "// Generated by generate_regfile. Structural" ++ << (functions.empty() ? "" : ", the periphery as assigns") << ".\n"; ++ Header(out, block->getName(), Buses(Ports(block))); + for (odb::dbNet* n : block->getNets()) { + if (n->getBTerms().begin() != n->getBTerms().end()) { + continue; // a port @@ -2006,13 +2190,6 @@ index 00000000000..fb4b113bda1 + } + out << " wire \\" << n->getName() << " ;\n"; + } -+ // A port net by its port name, buses with [i] intact; any other net -+ // escaped. -+ auto ref = [](odb::dbNet* n) { -+ return n->getBTerms().begin() != n->getBTerms().end() -+ ? n->getName() -+ : "\\" + n->getName() + " "; -+ }; + for (odb::dbInst* inst : block->getInsts()) { + auto f = functions.find(inst->getMaster()->getName()); + if (f != functions.end() && !inst->getPlacementStatus().isPlaced()) { @@ -2020,24 +2197,11 @@ index 00000000000..fb4b113bda1 + if (y == nullptr || y->getNet() == nullptr) { + continue; // drives nothing + } -+ std::string expr = f->second.expr; -+ for (size_t at = expr.find('@'); at != std::string::npos; -+ at = expr.find('@', at)) { -+ size_t end = at + 1; -+ while (end < expr.size() -+ && (std::isalnum(static_cast(expr[end])) -+ || expr[end] == '_')) { -+ ++end; -+ } -+ odb::dbITerm* in = inst->findITerm(expr.substr(at + 1, end - at - 1).c_str()); -+ const std::string r = in != nullptr && in->getNet() != nullptr -+ ? ref(in->getNet()) -+ : "1'b0"; -+ expr.replace(at, end - at, r); -+ at += r.size(); -+ } -+ out << " assign " << ref(y->getNet()) << " = " << expr << "; // " -+ << inst->getName() << "\n"; ++ out << Assign(f->second, inst->getName(), [&](const std::string& pin) { ++ odb::dbITerm* it = inst->findITerm(pin.c_str()); ++ return it != nullptr && it->getNet() != nullptr ? NetRef(it->getNet()) ++ : std::string(); ++ }); + continue; + } + out << " " << inst->getMaster()->getName() << " \\" << inst->getName() @@ -2065,6 +2229,86 @@ index 00000000000..fb4b113bda1 + out << "endmodule\n"; +} + ++// `periphery verilog` with `mode netlist`: the wrapper module in the RTL ++// module's place, the periphery as assigns and its clock gates as cells ++// around an instance of the core, and the core declared a blackbox for ++// synthesis; the core's netlist goes to .v beside it, for the flow ++// to dissolve. ++static void WriteWrapper(odb::dbBlock* block, ++ const std::string& path, ++ const Spec& spec) ++{ ++ const Wrapper& w = g_wrapper; ++ std::map functions = PeripheryFunctions(spec); ++ std::ofstream out(path); ++ if (!out) { ++ Refuse("cannot write " + path); ++ } ++ out << "// Generated by generate_regfile: the periphery around " ++ << w.core << ".\n"; ++ Header(out, w.module, Buses(w.ports)); ++ for (const auto& n : w.wires) { ++ if (n[0] == '\\') { ++ out << " wire " << n << ";\n"; ++ } ++ } ++ for (const auto& cell : w.cells) { ++ auto f = functions.find(cell.master); ++ auto net = [&](const std::string& pin) { ++ for (const auto& [p, n] : cell.conns) { ++ if (p == pin) { ++ return n; ++ } ++ } ++ return std::string(); ++ }; ++ if (f != functions.end()) { ++ if (!net(f->second.out).empty()) { ++ out << Assign(f->second, cell.name, net); ++ } ++ continue; ++ } ++ out << " " << cell.master << " \\" << cell.name << " ("; ++ for (size_t i = 0; i < cell.conns.size(); ++i) { ++ out << (i ? ", " : "") << "." << cell.conns[i].first << "(" ++ << cell.conns[i].second << ")"; ++ } ++ out << ");\n"; ++ } ++ // The core by its ports: a bus of the module's whole, a shared net bit ++ // by bit. ++ const auto core_buses = Buses(Ports(block)); ++ out << " " << w.core << " core ("; ++ for (size_t i = 0; i < core_buses.size(); ++i) { ++ const std::string& p = core_buses[i].first; ++ std::string n = p; ++ for (const auto& [port, net] : w.core_conns) { ++ if (port == p) { ++ n = net; ++ } ++ } ++ out << (i ? ", " : "") << "." << p << "(" << n << ")"; ++ } ++ out << ");\nendmodule\n\n(* blackbox *)\n"; ++ Header(out, w.core, core_buses); ++ out << "endmodule\n"; ++ const auto slash = path.rfind('/'); ++ const std::string dir ++ = slash == std::string::npos ? "" : path.substr(0, slash + 1); ++ WriteStructural(block, dir + w.core + ".v", spec); ++} ++ ++void WriteVerilog(odb::dbBlock* block, ++ const std::string& path, ++ const Spec& spec) ++{ ++ if (!g_wrapper.core.empty() && block->getName() == g_wrapper.core) { ++ WriteWrapper(block, path, spec); ++ } else { ++ WriteStructural(block, path, spec); ++ } ++} ++ +} // namespace ram::regfile diff --git a/src/ram/src/regfile.h b/src/ram/src/regfile.h new file mode 100644 @@ -2370,7 +2614,7 @@ new file mode 100644 index 00000000000..1fe0e3bba55 --- /dev/null +++ b/src/ram/src/views.cpp -@@ -0,0 +1,662 @@ +@@ -0,0 +1,752 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + @@ -2647,6 +2891,92 @@ index 00000000000..1fe0e3bba55 + writer.writeAbstractLef(block); +} + ++// The core of `periphery verilog` in `mode netlist`, _core: a ++// blackbox to synthesis and a macro to macro placement until it ++// dissolves, so its area and its pins, and no arcs; its ports are the ++// nets it shares with the periphery, which the spec's model knows ++// nothing of. ++static void WriteCoreLiberty(odb::dbBlock* block, const std::string& path) ++{ ++ std::ofstream o(path); ++ if (!o) { ++ throw std::runtime_error("cannot write " + path); ++ } ++ const std::string cell = block->getName(); ++ const odb::Rect die = block->getDieArea(); ++ const double dbu = block->getDbUnitsPerMicron(); ++ struct Bus ++ { ++ bool input = true; ++ int hi = -1; ++ }; ++ std::map buses; ++ std::vector order; ++ for (odb::dbBTerm* t : block->getBTerms()) { ++ if (t->getSigType() != odb::dbSigType::SIGNAL) { ++ continue; ++ } ++ std::string n = t->getName(); ++ int idx = -1; ++ const auto lb = n.rfind('['); ++ if (lb != std::string::npos && n.back() == ']') { ++ idx = std::stoi(n.substr(lb + 1, n.size() - lb - 2)); ++ n = n.substr(0, lb); ++ } ++ if (buses.find(n) == buses.end()) { ++ order.push_back(n); ++ buses[n].input = t->getIoType() == odb::dbIoType::INPUT; ++ } ++ buses[n].hi = std::max(buses[n].hi, idx); ++ } ++ o << "library(" << cell << ") {\n" ++ << " comment : \"generate_regfile: the core of a periphery verilog " ++ "register file, area and pins only\";\n" ++ << " delay_model : table_lookup;\n" ++ << " time_unit : \"1ns\";\n" ++ << " voltage_unit : \"1V\";\n" ++ << " current_unit : \"1uA\";\n" ++ << " leakage_power_unit : \"1uW\";\n" ++ << " capacitive_load_unit (1,pf);\n" ++ << " pulling_resistance_unit : \"1kohm\";\n" ++ << " nom_process : 1;\n" ++ << " nom_temperature : 25.000;\n" ++ << " nom_voltage : 0.700;\n"; ++ std::set widths; ++ for (const auto& [n, b] : buses) { ++ if (b.hi >= 0) { ++ widths.insert(b.hi + 1); ++ } ++ } ++ for (int w : widths) { ++ o << " type (" << cell << "_bus_" << w << ") {\n" ++ << " base_type : array ;\n" ++ << " data_type : bit ;\n" ++ << " bit_width : " << w << ";\n" ++ << " bit_from : " << w - 1 << ";\n" ++ << " bit_to : 0 ;\n" ++ << " downto : true ;\n" ++ << " }\n"; ++ } ++ o << "cell(" << cell << ") {\n" ++ << " area : " << F(die.dx() / dbu * (die.dy() / dbu)) << ";\n" ++ << " is_macro_cell : true;\n" ++ << " dont_touch : true;\n"; ++ for (const auto& n : order) { ++ const Bus& b = buses[n]; ++ const char* dir = b.input ? "input" : "output"; ++ if (b.hi < 0) { ++ o << " pin(" << n << ") {\n direction : " << dir ++ << ";\n capacitance : 0.001;\n }\n"; ++ } else { ++ o << " bus(" << n << ") {\n bus_type : " << cell << "_bus_" ++ << b.hi + 1 << ";\n direction : " << dir ++ << ";\n capacitance : 0.001;\n }\n"; ++ } ++ } ++ o << "}\n}\n"; ++} ++ +void WriteLiberty(odb::dbBlock* block, + const Spec& spec, + const LibModel& m, @@ -2657,6 +2987,10 @@ index 00000000000..1fe0e3bba55 + if (!o) { + throw std::runtime_error("cannot write " + path); + } ++ if (block->getName() != spec.module) { ++ WriteCoreLiberty(block, path); ++ return; ++ } + const std::string cell = spec.module; + const int A = AddrWidth(spec.words); + const int R = static_cast(spec.read.size()); diff --git a/patches/0108-orfs-regfile-periphery-verilog.patch b/patches/0108-orfs-regfile-periphery-verilog.patch new file mode 100644 index 000000000..1ae62e04c --- /dev/null +++ b/patches/0108-orfs-regfile-periphery-verilog.patch @@ -0,0 +1,70 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] AUTO_MEMORIES_REGFILES: periphery verilog in mode netlist + +A register file whose spec says `periphery verilog` and `mode netlist` +is generated (OpenROAD patch 0010) as a core, _core, and a +wrapper module in the RTL module's place: the periphery as assigns for +synthesis to map with the parent's logic, the clock gates as cells, +around an instance of the core. The wrapper is inlined (inline.txt); +the core is the macro: its abstract and liberty are _core.lef +and .lib, it joins blackboxes.txt and regfiles.txt, and it dissolves +from _core.v and .place after macro placement. + +On 0089 and 0091. Not upstreamed: AUTO_MEMORIES_REGFILES is carried +here only. Retires with 0089. + +--- +diff --git a/flow/scripts/memories/gen_memories.py b/flow/scripts/memories/gen_memories.py +--- a/flow/scripts/memories/gen_memories.py ++++ b/flow/scripts/memories/gen_memories.py +@@ -228,6 +228,7 @@ def run_regfiles( + ) + memories = [] + dissolve = [] ++ cores = [] + inline = [] + for spec, module in zip(specs, modules): + mode = _spec_mode(spec) +@@ -249,17 +250,25 @@ def run_regfiles( + f"gen_memories: {module} -> register file, inlined ({spec.name})\n" + ) + continue ++ # `periphery verilog` in mode netlist: the macro is the core ++ # alone, _core, and .v a wrapper of the periphery ++ # around it, read in the module's place like an inlined one ++ split = mode == "netlist" and _spec_value(spec, "periphery") == [["verilog"]] ++ block = f"{module}_core" if split else module + tcl.write_text( + "".join(f"read_lef {lef}\n" for lef in lefs) + + f"generate_regfile -spec {spec} -check_ports {rtl}" +- + f" -verilog {out_dir / f'{module}.v'} -def {out_dir / f'{module}.def'}" +- + f" -lef {out_dir / f'{module}.lef'} -liberty {out_dir / f'{module}.lib'}\n" ++ + f" -verilog {out_dir / f'{module}.v'} -def {out_dir / f'{block}.def'}" ++ + f" -lef {out_dir / f'{block}.lef'} -liberty {out_dir / f'{block}.lib'}\n" + ) + subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(tcl)]) + mem = _regfile_memory(spec, module, f"register file, mode {mode}") + if mode == "netlist": +- _def_placement(out_dir / f"{module}.def", out_dir / f"{module}.place") +- dissolve.append(module) ++ _def_placement(out_dir / f"{block}.def", out_dir / f"{block}.place") ++ dissolve.append(block) ++ if split: ++ inline.append(module) ++ cores.append(block) + memories.append(mem) + sys.stderr.write( + f"gen_memories: {module} -> register file, mode {mode} ({spec.name})\n" +@@ -267,9 +276,9 @@ def run_regfiles( + with (out_dir / "blackboxes.txt").open("a") as f: + f.write( + "".join( +- f"{m.name} {_lib_area(out_dir / f'{m.name}.lib')}\n" +- for m in memories +- if m.name not in inline ++ f"{name} {_lib_area(out_dir / f'{name}.lib')}\n" ++ for name in [m.name for m in memories if m.name not in inline] ++ + cores + ) + ) + (out_dir / "regfiles.txt").write_text("".join(f"{m}\n" for m in dissolve)) diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel index 914c21db3..1a7052d4d 100644 --- a/test/regfile/riscv32i/BUILD.bazel +++ b/test/regfile/riscv32i/BUILD.bazel @@ -61,6 +61,10 @@ NARROW = RISCV32I["arguments"] | {"RTLMP_MIN_CHANNEL_SIZE": "2 2"} "netlist_service0", {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, ), + ( + "netlist_verilog", + {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, + ), ( "macro", {"AUTO_MEMORIES_MACRO_PLACE": "regfile"}, @@ -71,21 +75,27 @@ NARROW = RISCV32I["arguments"] | {"RTLMP_MIN_CHANNEL_SIZE": "2 2"} # The netlist shape at 55 %, where AutoMemories.md measured the padded # abstract (959 ps on a 4 644 um2 core): at 62 % the four 42 um tall # FakeRAMs and the register file with its row halo do not tile. -orfs_flow( - name = "riscv_top", - arguments = NARROW | { - "AUTO_MEMORIES": "1", - "AUTO_MEMORIES_MACRO_PLACE": "regfile", - "CORE_UTILIZATION": "55", - }, - last_stage = "grt", - sources = SOURCES | { - "AUTO_MEMORIES_REGFILES": [":netlist.regfile"], - }, - tags = ["manual"], - variant = "netlist_narrow_55", - verilog_files = VERILOG_FILES, -) +[ + orfs_flow( + name = "riscv_top", + arguments = NARROW | { + "AUTO_MEMORIES": "1", + "AUTO_MEMORIES_MACRO_PLACE": "regfile", + "CORE_UTILIZATION": "55", + }, + last_stage = "grt", + sources = SOURCES | { + "AUTO_MEMORIES_REGFILES": [":%s.regfile" % regfile], + }, + tags = ["manual"], + variant = "%s_narrow_55" % regfile, + verilog_files = VERILOG_FILES, + ) + for regfile in [ + "netlist", + "netlist_verilog", + ] +] # odb-debug sessions on each stage, for ledger.tcl # and questions. @@ -103,6 +113,7 @@ orfs_flow( ("netlist_service0", ":riscv_top_netlist_service0_%s"), ("macro", ":riscv_top_macro_%s"), ("netlist_narrow_55", ":riscv_top_netlist_narrow_55_%s"), + ("netlist_verilog_narrow_55", ":riscv_top_netlist_verilog_narrow_55_%s"), ] + [ ( shape + "_narrow", diff --git a/test/regfile/riscv32i/ledger.tcl b/test/regfile/riscv32i/ledger.tcl index 52ef9ca3a..1f880a914 100644 --- a/test/regfile/riscv32i/ledger.tcl +++ b/test/regfile/riscv32i/ledger.tcl @@ -2,7 +2,8 @@ # core is in exactly one line: macros by master (box, halo ring), core # not covered by rows (cut around macros, margins), standard cells, # taps/endcaps, fill, and empty row area. The register file's cells -# (riscv.dp/rf/*) are split out of the standard cells, and their +# (riscv.dp/rf/*, or riscv.dp.rf/* where synthesis flattened a +# periphery wrapper) are split out of the standard cells, and their # bounding box and fill are reported once dissolved. set b [ord::get_db_block]; set u [expr double([$b getDbUnitsPerMicron])] proc um2 {a} { return [expr {$a/$::u/$::u}] } @@ -28,7 +29,7 @@ foreach i [$b getInsts] { if {[string match *WELLTAP $t] || [string match ENDCAP* $t] || [string match TAP* [$i getName]] || [string match PHY_* [$i getName]]} { set tap [expr {$tap+$a}]; continue } if {[string match *FILL* [$m getName]] || [string match *DECAP* [$m getName]]} { set fill [expr {$fill+$a}]; continue } if {![$i isPlaced]} { set unplaced [expr {$unplaced+$a}] } - if {[string match riscv.dp/rf/* [$i getName]]} { + if {[string match {riscv.dp[./]rf/*} [$i getName]]} { set rf [expr {$rf+$a}]; incr nrf if {[$i getPlacementStatus] eq "FIRM"} { set bb [$i getBBox]; set rfbox [expr {$rfbox+$a}] diff --git a/test/regfile/riscv32i/netlist_verilog.regfile b/test/regfile/riscv32i/netlist_verilog.regfile new file mode 100644 index 000000000..04d199e61 --- /dev/null +++ b/test/regfile/riscv32i/netlist_verilog.regfile @@ -0,0 +1,22 @@ +# riscv32i's regfile, macro-placed and then dissolved (mode netlist): +# its core fixed where the macro was placed, its address decode left to +# the parent. Otherwise as inlined.regfile. The periphery as assigns +# (periphery verilog): the macro is its core, regfile_core, and synthesis +# maps the periphery around it. +module regfile +mode netlist +periphery verilog +words 32 +bits 32 +clock clk +read ra1 rd1 +read ra2 rd2 +write wa3 wd3 we3 +zero_word 0 +write_style clock_gate +cell icg ICGx1_ASAP7_75t_R +cell flop DFFHQNx1_ASAP7_75t_R +cell and2 AND2x2_ASAP7_75t_R +cell or2 OR2x2_ASAP7_75t_R +cell ao22 AO22x2_ASAP7_75t_R +cell inv INVx1_ASAP7_75t_R diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 7056d025d..4c4b21af6 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -3,7 +3,8 @@ # src/riscv32i/regfile.v under random reads and writes, every read # compared. One netlist per write style: a hold mux per bit, and a clock # gate per word; and the clock gate with its periphery as assigns -# (`periphery verilog`). +# (`periphery verilog`), inlined and, in mode netlist, as a wrapper +# around the core's own netlist (regfile_core.v). load("@rules_cc//cc:defs.bzl", "cc_test") load("@rules_verilator//verilator:defs.bzl", "verilator_cc_library") load("@rules_verilog//verilog:defs.bzl", "verilog_library") @@ -33,7 +34,9 @@ stdcell_verilog( "@orfs//flow:platforms/asap7/lef/asap7_tech_1x_201209.lef", "@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef", ], - outs = ["regfile_%s.v" % style], + outs = ["regfile_%s.v" % style] + ( + ["regfile_core.v"] if "periphery verilog" in lines and "mode netlist" in lines else [] + ), cmd = """ grep -v '^write_style' $(location :regfile.regfile) > $(@D)/regfile_{style}.regfile {extra} @@ -43,7 +46,7 @@ read_lef $(location @orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a. generate_regfile -spec $(@D)/regfile_{style}.regfile -check_ports $(location @orfs//flow/designs/src/riscv32i:regfile.v) -verilog $(@D)/regfile_{style}.gen.v TCL $(location @openroad//:openroad) -exit -no_init -no_splash $(@D)/regfile_{style}.tcl > $(@D)/regfile_{style}.log 2>&1 || {{ cat $(@D)/regfile_{style}.log; exit 1; }} -sed 's/^module regfile(/module regfile_gen(/' $(@D)/regfile_{style}.gen.v > $@ +sed -e 's/^module regfile(/module regfile_gen(/' -e '/^(\\* blackbox \\*)$$/,$$d' $(@D)/regfile_{style}.gen.v > $(@D)/regfile_{style}.v """.format( extra = "\n".join([ "echo '%s' >> $(@D)/regfile_%s.regfile" % (line, style) @@ -58,6 +61,9 @@ sed 's/^module regfile(/module regfile_gen(/' $(@D)/regfile_{style}.gen.v > $@ srcs = [ "tb_top.v", ":regfile_%s.v" % style, + ] + ( + [":regfile_core.v"] if "periphery verilog" in lines and "mode netlist" in lines else [] + ) + [ ":asap7_stdcell.v", ":asap7_stdcell_empty.v", "@orfs//flow/designs/src/riscv32i:regfile.v", @@ -94,5 +100,13 @@ sed 's/^module regfile(/module regfile_gen(/' $(@D)/regfile_{style}.gen.v > $@ "periphery verilog", ], ), + ( + "netlist_verilog", + [ + "mode netlist", + "write_style clock_gate", + "periphery verilog", + ], + ), ] ] From 39e5df92b8742fddd202334b30d7e5bb85a31591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 08:03:00 +0200 Subject: [PATCH 09/26] lib_to_verilog: tristate outputs, quoted state variables, blocks per branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three gaps that kept Nangate45's cells from simulating: - A pin's `three_state` was ignored, so a tristate buffer was a plain buffer and every driver of a shared net drove it at once; it now releases the net (1'bz) while three_state holds. - `ff ("IQ" , "IQN")`, Nangate45's quoted state variables, did not parse, so DFF_X1 assigned Q from an undeclared IQ; ff and latch take them bare or quoted. - An asynchronous set or clear branch of a cell with Q and QN assigned both outputs without begin/end, a syntax error; each branch is now a block. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- tools/lib_to_verilog/lib_to_verilog.py | 26 +++++++-- tools/lib_to_verilog/lib_to_verilog_test.py | 63 +++++++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/tools/lib_to_verilog/lib_to_verilog.py b/tools/lib_to_verilog/lib_to_verilog.py index 90e6cd45c..b14bb4755 100644 --- a/tools/lib_to_verilog/lib_to_verilog.py +++ b/tools/lib_to_verilog/lib_to_verilog.py @@ -30,6 +30,9 @@ class Pin: name: str direction: str # "input", "output" or "internal" function: str = "" + # A tristate output: high impedance while this holds (Liberty's + # `three_state`). + three_state: str = "" # Liberty marks each pin of an integrated clock gate with its role, # which is the only portable way to tell ENA from SE: the pin names # are the vendor's to choose. @@ -177,6 +180,9 @@ def parse_lib_cells(text: str) -> list[Cell]: m = re.search(r'(? list[Cell]: current_pin = None # ff group start - m = re.search(r"ff\s*\(\s*(\w+)\s*,\s*(\w+)\s*\)", stripped) + # the state variables bare or quoted: ff (IQ,IQN), ff ("IQ" , "IQN") + m = re.search(r'ff\s*\(\s*"?(\w+)"?\s*,\s*"?(\w+)"?\s*\)', stripped) if m: cell.ff = FfInfo(var1=m.group(1), var2=m.group(2)) in_ff = True ff_depth = brace_depth # latch group start - m = re.search(r"latch\s*\(\s*(\w+)\s*,\s*(\w+)\s*\)", stripped) + m = re.search( + r'latch\s*\(\s*"?(\w+)"?\s*,\s*"?(\w+)"?\s*\)', stripped + ) if m: cell.latch = LatchInfo(var1=m.group(1), var2=m.group(2)) in_latch = True @@ -318,19 +327,23 @@ def generate_ff_verilog(cell: Cell) -> str: sens = ", ".join([f"posedge {clk_expr}"] + async_signals) lines.append(f" always @({sens}) begin") + # Each branch a block: a cell with both Q and QN assigns two + # outputs in it. if preset_expr: - lines.append(f" if ({preset_expr})") + lines.append(f" if ({preset_expr}) begin") # preset sets ff.var1 to 1 for name, expr in out_assigns: val = expr.replace("next_val", "1'b1").replace("~1'b1", "1'b0") lines.append(f" {name} <= {val};") + lines.append(" end") if clear_expr: kw = "else if" if preset_expr else "if" - lines.append(f" {kw} ({clear_expr})") + lines.append(f" {kw} ({clear_expr}) begin") # clear sets ff.var1 to 0 for name, expr in out_assigns: val = expr.replace("next_val", "1'b0").replace("~1'b0", "1'b1") lines.append(f" {name} <= {val};") + lines.append(" end") lines.append(" else begin") for name, expr in out_assigns: lines.append( @@ -601,6 +614,11 @@ def generate_combinational_verilog(cell: Cell) -> str: for p in outputs: if p.function: expr = liberty_expr_to_verilog(p.function) + if p.three_state: + # released while three_state holds, so drivers of a shared + # net (a tristate bitline) resolve + off = liberty_expr_to_verilog(p.three_state) + expr = f"({off}) ? 1'bz : ({expr})" lines.append(f" assign {p.name} = {expr};") spec = specify_block(cell) if spec: diff --git a/tools/lib_to_verilog/lib_to_verilog_test.py b/tools/lib_to_verilog/lib_to_verilog_test.py index 972b87827..871c72cb7 100644 --- a/tools/lib_to_verilog/lib_to_verilog_test.py +++ b/tools/lib_to_verilog/lib_to_verilog_test.py @@ -89,6 +89,36 @@ def test_simple_dff(self): assert c.ff.var2 == "IQN" assert len(c.pins) == 3 + def test_dff_quoted_state(self): + # Nangate45 quotes its state variables: ff ("IQ" , "IQN") + lib = textwrap.dedent( + """\ + library (test) { + cell (DFF_X1) { + pin (Q) { + direction : output; + function : "IQ"; + } + pin (D) { + direction : input; + } + pin (CK) { + direction : input; + } + ff ("IQ" , "IQN") { + next_state : "D"; + clocked_on : "CK"; + } + } + } + """ + ) + c = parse_lib_cells(lib)[0] + assert c.ff is not None + assert c.ff.var1 == "IQ" + assert c.ff.var2 == "IQN" + assert c.ff.clocked_on == "CK" + def test_dff_with_inverted_output(self): lib = textwrap.dedent( """\ @@ -479,6 +509,39 @@ def test_multi_output(self): assert "assign CO = A & B;" in v +class TestTristate(unittest.TestCase): + def test_tbuf(self): + # Nangate45's TBUF_X1: Z is high impedance while EN is high + lib = textwrap.dedent( + """\ + library (test) { + cell (TBUF_X1) { + pin (A) { + direction : input; + } + pin (EN) { + direction : input; + } + pin (Z) { + direction : output; + function : "A"; + three_state : "EN"; + timing () { + related_pin : "EN"; + timing_type : three_state_disable; + } + } + } + } + """ + ) + c = parse_lib_cells(lib)[0] + z = [p for p in c.pins if p.name == "Z"][0] + assert z.three_state == "EN" + v = generate_combinational_verilog(c) + assert "assign Z = (EN) ? 1'bz : (A);" in v, v + + class TestParseLefMacros(unittest.TestCase): def test_basic(self): lef = textwrap.dedent( From fb29cee815111b6fb659f5914e48b1dc31d3b76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 08:03:00 +0200 Subject: [PATCH 10/26] ram: generate_ram with more than one write port (patch 0011) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first generate_regfile feature carried onto generate_ram, Austin Rovinski's generator, as OpenROAD #11669's review asked: patch 0011, on 0010, one commit per future pull request. generate_ram took one read/write or one write port (RAM-0030). Now any number of write ports, each with its own decoder, data, write enables and address; one write port keeps its names, and generate_ram's four existing tests pass unchanged. A word written by two ports in a cycle keeps the last port's data, as the behavioral model does; the AO22 for the data is found by truth table, as the AOI22 is (an AOI22 and an inverter where the library has none, as on Nangate45). Not yet with -use_latch or -column_mux_ratio above 1. Tests: make_7x7_1r2w_nangate45, golden LEF, DEF and behavioral model in generate_ram's own format; and test/regfile/sim:ram_2w_sim_test, the netlist beside the behavioral model on Nangate45 under random writes on both ports, a quarter to the same word: 20 008 cycles, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 5 + ...11-openroad-ram-multiple-write-ports.patch | 5915 +++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 73 + test/regfile/sim/tb_ram_2w.cc | 48 + test/regfile/sim/tb_ram_2w.v | 23 + 6 files changed, 6065 insertions(+) create mode 100644 patches/0011-openroad-ram-multiple-write-ports.patch create mode 100644 test/regfile/sim/tb_ram_2w.cc create mode 100644 test/regfile/sim/tb_ram_2w.v diff --git a/MODULE.bazel b/MODULE.bazel index 0bd2279fc..a7413e922 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -127,6 +127,11 @@ archive_override( # The-OpenROAD-Project/OpenROAD#11669; retires at a bump onto an # OpenROAD that has it. "//patches:0010-openroad-ram-generate-regfile.patch", + # 0011: generate_ram with more than one write port, each with its + # own decoder and data, the last port winning a word both write. + # The first generate_regfile feature carried onto generate_ram + # (OpenROAD #11669); not upstreamed. + "//patches:0011-openroad-ram-multiple-write-ports.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0011-openroad-ram-multiple-write-ports.patch b/patches/0011-openroad-ram-multiple-write-ports.patch new file mode 100644 index 000000000..d00f0cb19 --- /dev/null +++ b/patches/0011-openroad-ram-multiple-write-ports.patch @@ -0,0 +1,5915 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram with more than one write port + +generate_ram took exactly one read/write or one write port (RAM-0030). +It now takes any number of write ports: each has its own address +decoder, data bus (D0, D1, ...), write enables (we0, we1, ...) and +address (addr_w0, addr_w1, ...); one write port keeps the names it had. +Per word, port w writes when its row select and write enable are high; +a word written by two ports in a cycle keeps the last one's data, as +the behavioral model does; the word's clock gate opens for any of them. +Per bit an AO22 per pair of ports, and an OR2 across pairs, picks the +data. The AO22 is found by its truth table, as the AOI22 is, through +findMaster4, which both now share; the OR2 by its function. + +Not yet with -use_latch, whose data passes a latch per column, or with +-column_mux_ratio above 1, whose word select comes from the first +port's address (RAM-0054, RAM-0055). + +The first of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 1c921505d2..008107da2d 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -62,9 +62,9 @@ generate_ram [-mask_size bits] + | `-mask_size` | Determines the number of bits which are grouped together for masking during writes. For example, a mask size of `8` will enable each 8 bits of the word to be masked when writing (commonly known as byte masking). A mask size of `1` will enable each bit to be individually masked. The write enable signal for each port will be `(word_size / mask_size)` bits wide. The word size must be a multiple of the mask size. Default: equal to `-word_size`. | + | `-word_size` | Size of each word in bits. | + | `-num_words` | Number of words in the array. | +-| `-rw_ports` | Number of read-write ports for the array. Sum of read-write ports and write ports must equal 1. Default: 1. | ++| `-rw_ports` | Number of read-write ports for the array: 0 or 1, and a read-write port is the only write port. Default: 1. | + | `-r_ports` | Number of read ports for the array. Default: 0. | +-| `-w_ports` | Number of write ports for the array. Sum of read-write ports and write ports must equal 1. Default: 0. | ++| `-w_ports` | Number of write ports for the array. With more than one, each has its own address decoder, data (`D0`, `D1`, ...), write enables (`we0`, ...) and address (`addr_w0`, ...); a word two ports write in the same cycle keeps the last port's data. Not yet with `-use_latch` or `-column_mux_ratio` above 1. Default: 0. | + | `-column_mux_ratio` | Number of words sharing a physical column. Must be `1`, `2`, or `4`. The number of words must be divisible by the column mux ratio. Default: `1` (no column muxing). | + | `-storage_cell` | Name of the master to use for the storage device (i.e. a flip-flop). Must be positive-edge triggered. Default: auto-select from the loaded cell library. | + | `-tristate_cell` | Name of the master to use for the tristate device (i.e. a tristate inverter). It is currently assumed that the device is inverting. Default: auto-select from the loaded cell library. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 1a41ba0d7b..3b9844cbae 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -4,6 +4,7 @@ + #pragma once + + #include ++#include + #include + #include + #include +@@ -135,8 +136,19 @@ class RamGen + private: + void findMasters(); + std::map buildPortMap(odb::dbMaster*); ++ // The smallest cell `match` accepts; none is an error unless not ++ // `required`, then nullptr. + odb::dbMaster* findMaster(const std::function& match, +- const char* name); ++ const char* name, ++ bool required = true); ++ // The smallest four-input cell whose function is `table` (bit k the ++ // output for inputs k in binary, in the order of `inputs`): `inputs` ++ // gets its input pins in that order, `output` its output pin. ++ odb::dbMaster* findMaster4(uint16_t table, ++ const char* name, ++ std::array& inputs, ++ std::string& output, ++ bool required = true); + odb::dbNet* makeNet(const std::string& prefix, const std::string& name); + odb::dbInst* makeInst( + Cell* cell, +@@ -159,12 +171,12 @@ class RamGen + int word_idx, + int column_mux_ratio, + odb::dbNet* clock, +- odb::dbNet* write_enable, ++ const std::vector& write_enable, + odb::dbNet* word_select, + const std::vector& selects, + const std::vector& shared_select_b_nets, + bool create_select_inv, +- const std::vector& data_input, ++ const std::vector>& data_input, + const std::vector>& data_output); + + void makeWord(int slices_per_word, +@@ -177,11 +189,11 @@ class RamGen + int column_mux_ratio, + odb::dbNet* clock, + odb::dbNet* word_select, +- std::vector& write_enable, ++ std::vector>& write_enable, + const std::vector& selects, + const std::vector& shared_select_b_nets, + bool create_select_inv, +- const std::vector& data_input, ++ const std::vector>& data_input, + const std::vector>& data_output); + + odb::dbBTerm* makeBTerm(const std::string& name, odb::dbIoType io_type); +@@ -229,6 +241,11 @@ class RamGen + odb::dbMaster* clock_gate_cell_{nullptr}; + odb::dbMaster* buffer_cell_{nullptr}; + odb::dbMaster* aoi22_cell_{nullptr}; ++ // with more than one write port: the write data mux (an AO22, or where ++ // the library has none the AOI22 and an inverter) and the write ++ // enables' OR ++ odb::dbMaster* ao22_cell_{nullptr}; ++ odb::dbMaster* or2_cell_{nullptr}; + odb::dbMaster* latch_cell_{nullptr}; + odb::dbMaster* tapcell_{nullptr}; + +@@ -242,15 +259,19 @@ class RamGen + std::map clock_gate_ports_; + std::map buffer_ports_; + std::map latch_ports_; ++ std::map or2_ports_; + + std::vector> addr_inputs_; +- std::vector data_inputs_; ++ std::vector data_inputs_; // every write port's data + std::vector> q_outputs_; + std::string behavioral_verilog_filename_; + std::string aoi22_in_a1_, aoi22_in_a2_, aoi22_in_b1_, aoi22_in_b2_, + aoi22_out_; ++ std::array ao22_in_; ++ std::string ao22_out_; + Grid ram_grid_; + bool use_latch_{false}; ++ int num_write_{1}; // write and read/write ports + }; + + } // namespace ram +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 2d2c537800..7e97ae2600 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -4,6 +4,7 @@ + #include "ram/ram.h" + + #include ++#include + #include + #include + #include +@@ -169,14 +170,16 @@ void RamGen::makeSlice(const int slice_idx, + const int word_idx, + const int column_mux_ratio, + dbNet* clock, +- dbNet* write_enable, ++ const vector& write_enable, + dbNet* word_select, + const vector& selects, + const vector& shared_select_b_nets, + const bool create_select_inv, +- const vector& data_input, ++ const vector>& data_input, + const vector>& data_output) + { ++ // selects: the write ports' row selects, then the read ports' ++ const int num_write = rw_ports + w_ports; + const int start_bit_idx = slice_idx * mask_size; + std::string prefix + = fmt::format("storage_{}_{}_{}", row_idx, word_idx, start_bit_idx); +@@ -193,6 +196,57 @@ void RamGen::makeSlice(const int slice_idx, + + auto gclock_net = makeNet(prefix, "gclock"); + auto we_net = makeNet(prefix, "we"); ++ auto sel_cell = std::make_unique(); ++ ++ // More than one write port: port w writes this word when its row select ++ // and its write enable are both high (we{w}), and its data is taken ++ // unless a later port writes the word in the same cycle (take{w}): the ++ // last port wins, as in the behavioral model. The clock gate opens for ++ // any of them. ++ vector take(num_write); ++ if (num_write > 1) { ++ vector we(num_write); ++ for (int w = 0; w < num_write; ++w) { ++ we[w] = makeNet(prefix, fmt::format("we{}", w)); ++ makeInst(sel_cell.get(), ++ prefix, ++ fmt::format("gcand{}", w), ++ and2_cell_, ++ {{and2_ports_[{PortRoleType::DataIn, 0}], selects[w]}, ++ {and2_ports_[{PortRoleType::DataIn, 1}], write_enable[w]}, ++ {and2_ports_[{PortRoleType::DataOut, 0}], we[w]}}); ++ } ++ take[num_write - 1] = we[num_write - 1]; ++ dbNet* later = we[num_write - 1]; ++ for (int w = num_write - 2; w >= 0; --w) { ++ auto later_b = makeNet(prefix, fmt::format("later{}_b", w)); ++ makeInst(sel_cell.get(), ++ prefix, ++ fmt::format("later_inv{}", w), ++ inv_cell_, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], later}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], later_b}}); ++ take[w] = makeNet(prefix, fmt::format("take{}", w)); ++ makeInst(sel_cell.get(), ++ prefix, ++ fmt::format("take_and{}", w), ++ and2_cell_, ++ {{and2_ports_[{PortRoleType::DataIn, 0}], we[w]}, ++ {and2_ports_[{PortRoleType::DataIn, 1}], later_b}, ++ {and2_ports_[{PortRoleType::DataOut, 0}], take[w]}}); ++ // any port from w on writes: the next earlier port's later, and at ++ // port 0 the clock gate's enable ++ auto any = w == 0 ? we_net : makeNet(prefix, fmt::format("later{}", w)); ++ makeInst(sel_cell.get(), ++ prefix, ++ fmt::format("any_or{}", w), ++ or2_cell_, ++ {{or2_ports_[{PortRoleType::DataIn, 0}], later}, ++ {or2_ports_[{PortRoleType::DataIn, 1}], we[w]}, ++ {or2_ports_[{PortRoleType::DataOut, 0}], any}}); ++ later = any; ++ } ++ } + + for (int local_bit = 0; local_bit < mask_size; ++local_bit) { + auto name = fmt::format("{}.bit{}", prefix, start_bit_idx + local_bit); +@@ -201,19 +255,78 @@ void RamGen::makeSlice(const int slice_idx, + outs[r_port] = data_output[r_port][local_bit]; + } + ++ dbNet* d = data_input[0][local_bit]; ++ if (num_write > 1) { ++ d = makeNet(name, "d"); ++ } ++ auto bit_cell ++ = makeBit(name, r_total, gclock_net, select_b_nets, d, outs); ++ if (num_write > 1) { ++ // the taken port's data: AO22 over pairs of ports, OR2 across pairs ++ dbNet* acc = nullptr; ++ for (int w = 0; w < num_write; w += 2) { ++ const bool last = w + 2 >= num_write; ++ dbNet* out = last && acc == nullptr ++ ? d ++ : makeNet(name, fmt::format("d_pair{}", w / 2)); ++ if (w + 1 < num_write && !ao22_cell_) { ++ // no AO22 in the library: the AOI22 and an inverter ++ auto out_b = makeNet(name, fmt::format("d_pair{}_b", w / 2)); ++ makeInst(bit_cell.get(), ++ name, ++ fmt::format("dmux{}", w / 2), ++ aoi22_cell_, ++ {{aoi22_in_a1_, take[w]}, ++ {aoi22_in_a2_, data_input[w][local_bit]}, ++ {aoi22_in_b1_, take[w + 1]}, ++ {aoi22_in_b2_, data_input[w + 1][local_bit]}, ++ {aoi22_out_, out_b}}); ++ makeInst(bit_cell.get(), ++ name, ++ fmt::format("dmux{}_inv", w / 2), ++ inv_cell_, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], out_b}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], out}}); ++ } else if (w + 1 < num_write) { ++ makeInst(bit_cell.get(), ++ name, ++ fmt::format("dmux{}", w / 2), ++ ao22_cell_, ++ {{ao22_in_[0], take[w]}, ++ {ao22_in_[1], data_input[w][local_bit]}, ++ {ao22_in_[2], take[w + 1]}, ++ {ao22_in_[3], data_input[w + 1][local_bit]}, ++ {ao22_out_, out}}); ++ } else { ++ makeInst(bit_cell.get(), ++ name, ++ fmt::format("dmux{}", w / 2), ++ and2_cell_, ++ {{and2_ports_[{PortRoleType::DataIn, 0}], take[w]}, ++ {and2_ports_[{PortRoleType::DataIn, 1}], ++ data_input[w][local_bit]}, ++ {and2_ports_[{PortRoleType::DataOut, 0}], out}}); ++ } ++ if (acc != nullptr) { ++ dbNet* sum = last ? d : makeNet(name, fmt::format("d_or{}", w / 2)); ++ makeInst(bit_cell.get(), ++ name, ++ fmt::format("dor{}", w / 2), ++ or2_cell_, ++ {{or2_ports_[{PortRoleType::DataIn, 0}], acc}, ++ {or2_ports_[{PortRoleType::DataIn, 1}], out}, ++ {or2_ports_[{PortRoleType::DataOut, 0}], sum}}); ++ out = sum; ++ } ++ acc = out; ++ } ++ } ++ + int bit_col = slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) + + local_bit * column_mux_ratio + word_idx; +- ram_grid_.addCell(makeBit(name, +- r_total, +- gclock_net, +- select_b_nets, +- data_input[local_bit], +- outs), +- bit_col); ++ ram_grid_.addCell(std::move(bit_cell), bit_col); + } + +- auto sel_cell = std::make_unique(); +- + // Make clock gate + makeInst(sel_cell.get(), + prefix, +@@ -226,8 +339,8 @@ void RamGen::makeSlice(const int slice_idx, + // Write path: this net is row_select AND with word_select so clock gate only + // fires for the addressed word within the row. Read path handled by AOI mux. + // word_select is nullptr when column_mux_ratio=1 (no mux needed). +- dbNet* write_sel = selects[0]; +- if (word_select) { ++ dbNet* write_sel = num_write > 1 ? nullptr : selects[0]; ++ if (word_select && num_write == 1) { + write_sel = makeNet(prefix, "write_sel"); + makeInst(sel_cell.get(), + prefix, +@@ -241,13 +354,15 @@ void RamGen::makeSlice(const int slice_idx, + // Make clock and + // this AND gate needs to be fed a net created by a decoder + // adding any net will automatically connect with any port +- makeInst(sel_cell.get(), +- prefix, +- "gcand", +- and2_cell_, +- {{and2_ports_[{PortRoleType::DataIn, 0}], write_sel}, +- {and2_ports_[{PortRoleType::DataIn, 1}], write_enable}, +- {and2_ports_[{PortRoleType::DataOut, 0}], we_net}}); ++ if (num_write == 1) { ++ makeInst(sel_cell.get(), ++ prefix, ++ "gcand", ++ and2_cell_, ++ {{and2_ports_[{PortRoleType::DataIn, 0}], write_sel}, ++ {and2_ports_[{PortRoleType::DataIn, 1}], write_enable[0]}, ++ {and2_ports_[{PortRoleType::DataOut, 0}], we_net}}); ++ } + + // Make select inverters + if (create_select_inv) { +@@ -256,7 +371,7 @@ void RamGen::makeSlice(const int slice_idx, + prefix, + fmt::format("select_inv_{}", i), + inv_cell_, +- {{inv_ports_[{PortRoleType::DataIn, 0}], selects[i + 1]}, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], selects[num_write + i]}, + {inv_ports_[{PortRoleType::DataOut, 0}], select_b_nets[i]}}); + } + } +@@ -283,18 +398,24 @@ void RamGen::makeWord(const int slices_per_word, + const int column_mux_ratio, + dbNet* clock, + dbNet* word_select, +- vector& write_enable, ++ vector>& write_enable, + const vector& selects, + const vector& shared_select_b_nets, + const bool create_select_inv, +- const vector& data_input, ++ const vector>& data_input, + const vector>& data_output) + { + int r_total = rw_ports + r_ports; + for (int slice = 0; slice < slices_per_word; ++slice) { + int start_idx = slice * mask_size; +- vector slice_inputs(data_input.begin() + start_idx, +- data_input.begin() + start_idx + mask_size); ++ // per write port: its data bits and its write enable for this slice ++ vector> slice_inputs; ++ vector slice_enables; ++ for (size_t w = 0; w < data_input.size(); ++w) { ++ slice_inputs.emplace_back(data_input[w].begin() + start_idx, ++ data_input[w].begin() + start_idx + mask_size); ++ slice_enables.push_back(write_enable[w][slice]->getNet()); ++ } + std::vector> slice_outputs; + slice_outputs.reserve(r_total); + for (int port = 0; port < r_total; ++port) { +@@ -311,7 +432,7 @@ void RamGen::makeWord(const int slices_per_word, + word_idx, + column_mux_ratio, + clock, +- write_enable[slice]->getNet(), ++ slice_enables, + word_select, + selects, + shared_select_b_nets, +@@ -478,7 +599,8 @@ std::vector RamGen::makeSelectNets(const std::string& prefix, + + dbMaster* RamGen::findMaster( + const std::function& match, +- const char* name) ++ const char* name, ++ const bool required) + { + dbMaster* best = nullptr; + float best_area = std::numeric_limits::max(); +@@ -531,6 +653,9 @@ dbMaster* RamGen::findMaster( + } + + if (!best) { ++ if (!required) { ++ return nullptr; ++ } + logger_->error(RAM, 10, "Can't find {} cell", name); + } + logger_->info(RAM, 16, "Selected {} cell {}", name, best->getName()); +@@ -780,141 +905,177 @@ void RamGen::findMasters() + // to work for all PDKs, avoiding hardcoding PDK-specific expression parsing + if (!aoi22_cell_) { + // AOI22 truth table: Y = !(A1&A2 | B1&B2) +- // for 4 inputs ordered (A1,A2,B1,B2) mapped to bits (0,1,2,3), +- // bit k of the table = output when inputs = k in binary. +- // kAoi22Table holds the expected output values column for aoi22 truth table +- static const uint16_t kAoi22Table = 0x0777; +- +- // recursively evaluate a liberty function expression given input port +- // values +- std::function&, +- const std::vector&)> +- evalFunc; +- +- evalFunc = [&evalFunc](const sta::FuncExpr* expr, +- const std::vector& ports, +- const std::vector& vals) -> bool { +- if (!expr) { +- return false; +- } +- switch (expr->op()) { +- case sta::FuncExpr::Op::port: { +- // look up this port's value in the input vector +- auto p = expr->port(); +- for (int i = 0; i < (int) ports.size(); ++i) { +- if (ports[i] == p) { +- return vals[i]; ++ std::array in; ++ aoi22_cell_ = findMaster4(0x0777, "aoi22", in, aoi22_out_); ++ aoi22_in_a1_ = in[0]; ++ aoi22_in_a2_ = in[1]; ++ aoi22_in_b1_ = in[2]; ++ aoi22_in_b2_ = in[3]; ++ } ++ ++ // More than one write port: the write data mux, an AO22 per pair of ++ // ports, and an OR2 for the write enables and across pairs. ++ if (num_write_ > 1) { ++ if (!ao22_cell_) { ++ // AO22 truth table: Y = A1&A2 | B1&B2 ++ ao22_cell_ = findMaster4( ++ 0xF888, "ao22", ao22_in_, ao22_out_, /*required=*/false); ++ } ++ if (!or2_cell_) { ++ or2_cell_ = findMaster( ++ [](sta::LibertyPort* port) { ++ if (!port->direction()->isOutput()) { ++ return false; + } ++ auto function = port->function(); ++ return function && function->op() == sta::FuncExpr::Op::or_ ++ && function->left()->op() == sta::FuncExpr::Op::port ++ && function->right()->op() == sta::FuncExpr::Op::port; ++ }, ++ "or2"); ++ } ++ or2_ports_ = buildPortMap(or2_cell_); ++ } ++} ++ ++dbMaster* RamGen::findMaster4(const uint16_t table, ++ const char* name, ++ std::array& inputs_out, ++ std::string& output, ++ const bool required) ++{ ++ // for 4 inputs ordered (A1,A2,B1,B2) mapped to bits (0,1,2,3), ++ // bit k of the table = output when inputs = k in binary. ++ ++ // recursively evaluate a liberty function expression given input port ++ // values ++ std::function&, ++ const std::vector&)> ++ evalFunc; ++ ++ evalFunc = [&evalFunc](const sta::FuncExpr* expr, ++ const std::vector& ports, ++ const std::vector& vals) -> bool { ++ if (!expr) { ++ return false; ++ } ++ switch (expr->op()) { ++ case sta::FuncExpr::Op::port: { ++ // look up this port's value in the input vector ++ auto p = expr->port(); ++ for (int i = 0; i < (int) ports.size(); ++i) { ++ if (ports[i] == p) { ++ return vals[i]; + } +- return false; + } +- case sta::FuncExpr::Op::not_: +- return !evalFunc(expr->left(), ports, vals); +- case sta::FuncExpr::Op::and_: +- return evalFunc(expr->left(), ports, vals) +- && evalFunc(expr->right(), ports, vals); +- case sta::FuncExpr::Op::or_: +- return evalFunc(expr->left(), ports, vals) +- || evalFunc(expr->right(), ports, vals); +- case sta::FuncExpr::Op::xor_: +- return evalFunc(expr->left(), ports, vals) +- != evalFunc(expr->right(), ports, vals); +- case sta::FuncExpr::Op::one: +- return true; +- case sta::FuncExpr::Op::zero: +- return false; +- default: +- return false; ++ return false; ++ } ++ case sta::FuncExpr::Op::not_: ++ return !evalFunc(expr->left(), ports, vals); ++ case sta::FuncExpr::Op::and_: ++ return evalFunc(expr->left(), ports, vals) ++ && evalFunc(expr->right(), ports, vals); ++ case sta::FuncExpr::Op::or_: ++ return evalFunc(expr->left(), ports, vals) ++ || evalFunc(expr->right(), ports, vals); ++ case sta::FuncExpr::Op::xor_: ++ return evalFunc(expr->left(), ports, vals) ++ != evalFunc(expr->right(), ports, vals); ++ case sta::FuncExpr::Op::one: ++ return true; ++ case sta::FuncExpr::Op::zero: ++ return false; ++ default: ++ return false; ++ } ++ }; ++ ++ // compute 16-entry truth table for a function given 4 ordered input ports. ++ // each bit k of the result = output when inputs = k in binary. (i.e. k= 2 = ++ // 10) ++ auto computeTable = ++ [&evalFunc](const sta::FuncExpr* func, ++ const std::vector& inputs) -> uint16_t { ++ uint16_t table = 0; ++ for (int k = 0; k < 16; ++k) { ++ std::vector vals(4); ++ for (int i = 0; i < 4; ++i) { ++ vals[i] = (k >> i) & 1; + } +- }; +- +- // compute 16-entry truth table for a function given 4 ordered input ports. +- // each bit k of the result = output when inputs = k in binary. (i.e. k= 2 = +- // 10) +- auto computeTable = +- [&evalFunc](const sta::FuncExpr* func, +- const std::vector& inputs) -> uint16_t { +- uint16_t table = 0; +- for (int k = 0; k < 16; ++k) { +- std::vector vals(4); +- for (int i = 0; i < 4; ++i) { +- vals[i] = (k >> i) & 1; ++ if (evalFunc(func, inputs, vals)) { ++ table |= (1 << k); ++ } ++ } ++ return table; ++ }; ++ ++ // there are exactly 3 unique ways to split 4 ports into 2 pairs for AOI22, ++ // each pairing assigns (inputs[0],inputs[1]) to group A and ++ // (inputs[2],inputs[3]) to group B. Try all 3 and check which pattern ++ // pairing produces the correct AOI22 truth table, which is the correct port ++ // mapping ++ static const int kPairings[3][4] = { ++ {0, 1, 2, 3}, // group A=(p0,p1), group B=(p2,p3) ++ {0, 2, 1, 3}, // group A=(p0,p2), group B=(p1,p3) ++ {0, 3, 1, 2}, // group A=(p0,p3), group B=(p1,p2) ++ }; ++ ++ return findMaster( ++ [&](sta::LibertyPort* out_port) -> bool { ++ if (!out_port->direction()->isOutput()) { ++ return false; + } +- if (evalFunc(func, inputs, vals)) { +- table |= (1 << k); ++ auto func = out_port->function(); ++ if (!func) { ++ return false; + } +- } +- return table; +- }; +- +- // there are exactly 3 unique ways to split 4 ports into 2 pairs for AOI22, +- // each pairing assigns (inputs[0],inputs[1]) to group A and +- // (inputs[2],inputs[3]) to group B. Try all 3 and check which pattern +- // pairing produces the correct AOI22 truth table, which is the correct port +- // mapping +- static const int kPairings[3][4] = { +- {0, 1, 2, 3}, // group A=(p0,p1), group B=(p2,p3) +- {0, 2, 1, 3}, // group A=(p0,p2), group B=(p1,p3) +- {0, 3, 1, 2}, // group A=(p0,p3), group B=(p1,p2) +- }; +- +- aoi22_cell_ = findMaster( +- [&](sta::LibertyPort* out_port) -> bool { +- if (!out_port->direction()->isOutput()) { +- return false; +- } +- auto func = out_port->function(); +- if (!func) { +- return false; +- } +- auto cell = out_port->libertyCell(); +- +- // collect all input ports for this cell +- std::vector inputs; +- std::unique_ptr port_iter( +- cell->portIterator()); +- while (port_iter->hasNext()) { +- auto p = static_cast(port_iter->next()); +- if (p->direction()->isInput()) { +- inputs.push_back(p->libertyPort()); +- } ++ auto cell = out_port->libertyCell(); ++ ++ // collect all input ports for this cell ++ std::vector inputs; ++ std::unique_ptr port_iter( ++ cell->portIterator()); ++ while (port_iter->hasNext()) { ++ auto p = static_cast(port_iter->next()); ++ if (p->direction()->isInput()) { ++ inputs.push_back(p->libertyPort()); + } ++ } + +- // aoi22 must have exactly 4 inputs +- if (inputs.size() != 4) { +- return false; +- } ++ // aoi22 must have exactly 4 inputs ++ if (inputs.size() != 4) { ++ return false; ++ } + +- // sort ports by name for deterministic ordering across builds +- std::ranges::sort( +- inputs, [](sta::LibertyPort* a, sta::LibertyPort* b) { +- return std::string(a->name()) < std::string(b->name()); +- }); +- +- // try each pairing, if truth table matches, record port names +- for (auto& pairing : kPairings) { +- std::vector ordered = {inputs[pairing[0]], +- inputs[pairing[1]], +- inputs[pairing[2]], +- inputs[pairing[3]]}; +- if (computeTable(func, ordered) == kAoi22Table) { +- // found matching pairing so this is the correct port mapping, +- // store port names for later use +- // ordered[0] = A1, ordered[1] = A2, ordered[2] = B1, ordered[3] = +- // B2 +- aoi22_in_a1_ = ordered[0]->name(); +- aoi22_in_a2_ = ordered[1]->name(); +- aoi22_in_b1_ = ordered[2]->name(); +- aoi22_in_b2_ = ordered[3]->name(); +- aoi22_out_ = out_port->name(); +- return true; ++ // sort ports by name for deterministic ordering across builds ++ std::ranges::sort( ++ inputs, [](sta::LibertyPort* a, sta::LibertyPort* b) { ++ return std::string(a->name()) < std::string(b->name()); ++ }); ++ ++ // try each pairing, if truth table matches, record port names ++ for (auto& pairing : kPairings) { ++ std::vector ordered = {inputs[pairing[0]], ++ inputs[pairing[1]], ++ inputs[pairing[2]], ++ inputs[pairing[3]]}; ++ if (computeTable(func, ordered) == table) { ++ // found matching pairing so this is the correct port mapping, ++ // store port names for later use ++ // ordered[0] = A1, ordered[1] = A2, ordered[2] = B1, ordered[3] = ++ // B2 ++ for (int i = 0; i < 4; ++i) { ++ inputs_out[i] = ordered[i]->name(); + } ++ output = out_port->name(); ++ return true; + } +- return false; +- }, +- "aoi22"); +- } ++ } ++ return false; ++ }, ++ name, ++ required); + } + + void RamGen::ramPdngen(const char* power_net_name, +@@ -1095,7 +1256,11 @@ void RamGen::ramPinplacer(const char* ver_name, const char* hor_name) + std::string name = bterm->getName(); + if (name == "clk") { + clk_pins.push_back(bterm); +- } else if (name.starts_with("we[")) { ++ } else if (name.starts_with("we") ++ && name.find('[') != std::string::npos ++ && std::all_of(name.begin() + 2, ++ name.begin() + name.find('['), ++ [](char c) { return std::isdigit(c); })) { + we_pins.push_back(bterm); + } + } +@@ -1201,6 +1366,7 @@ void RamGen::generate(const int mask_size, + logger_->info(RAM, 3, "Generating {}", ram_name); + + use_latch_ = use_latch; ++ num_write_ = rw_ports + w_ports; + storage_cell_ = storage_cell; + tristate_cell_ = tristate_cell; + inv_cell_ = inv_cell; +@@ -1209,6 +1375,8 @@ void RamGen::generate(const int mask_size, + clock_gate_cell_ = nullptr; + buffer_cell_ = nullptr; + aoi22_cell_ = nullptr; ++ ao22_cell_ = nullptr; ++ or2_cell_ = nullptr; + latch_cell_ = nullptr; + + if (use_latch_ && storage_cell_) { +@@ -1270,10 +1438,17 @@ void RamGen::generate(const int mask_size, + + auto clock = makeBTerm("clk", dbIoType::INPUT); + +- vector write_enable(slices_per_word, nullptr); +- for (int slice = 0; slice < slices_per_word; ++slice) { +- auto in_name = fmt::format("we[{}]", slice); +- write_enable[slice] = makeBTerm(in_name, dbIoType::INPUT); ++ // One write enable bus per write port: we, or with more than one write ++ // port we0, we1, ... ++ const int num_write = num_write_; ++ vector> write_enable( ++ num_write, vector(slices_per_word, nullptr)); ++ for (int w = 0; w < num_write; ++w) { ++ const std::string we = num_write == 1 ? "we" : fmt::format("we{}", w); ++ for (int slice = 0; slice < slices_per_word; ++slice) { ++ write_enable[w][slice] ++ = makeBTerm(fmt::format("{}[{}]", we, slice), dbIoType::INPUT); ++ } + } + + // When column_mux_ratio > 1: word_sel_nets[word_idx] is high/active when +@@ -1311,7 +1486,7 @@ void RamGen::generate(const int mask_size, + port_prefix = "addr_rw"; + rw_idx++; + } else if (p < rw_ports + w_ports) { +- port_prefix = "addr_w"; ++ port_prefix = num_write == 1 ? "addr_w" : fmt::format("addr_w{}", w_idx); + w_idx++; + } else { + port_prefix = fmt::format("addr_r{}", r_idx++); +@@ -1370,11 +1545,18 @@ void RamGen::generate(const int mask_size, + // start of input/output net creation + int r_total = rw_ports + r_ports; + q_outputs_.resize(r_total); +- vector D_nets(word_size); ++ // One data bus per write port: D, or with more than one D0, D1, ... ++ vector> data_inputs(num_write); ++ vector> D_nets(num_write, vector(word_size)); + for (int bit = 0; bit < word_size; ++bit) { +- data_inputs_.push_back( +- makeBTerm(fmt::format("D[{}]", bit), dbIoType::INPUT)); +- D_nets[bit] = makeNet("D_nets", fmt::format("b{}", bit)); ++ for (int w = 0; w < num_write; ++w) { ++ const std::string d = num_write == 1 ? "D" : fmt::format("D{}", w); ++ data_inputs[w].push_back( ++ makeBTerm(fmt::format("{}[{}]", d, bit), dbIoType::INPUT)); ++ data_inputs_.push_back(data_inputs[w].back()); ++ D_nets[w][bit] = makeNet(num_write == 1 ? "D_nets" : d + "_nets", ++ fmt::format("b{}", bit)); ++ } + + // if total read ports == 1, only have Q outputs + if (r_total == 1) { +@@ -1451,14 +1633,13 @@ void RamGen::generate(const int mask_size, + } + + for (int word_idx = 0; word_idx < column_mux_ratio; ++word_idx) { +- // size of row_selects is write port and total num read ports +- vector row_selects(r_total + 1); +- for (int p = 0; p < rw_ports + w_ports; ++p) { ++ // the write ports' row selects, then the read ports' ++ vector row_selects(num_write + r_total); ++ for (int p = 0; p < num_write; ++p) { + row_selects[p] = write_select_nets[p][row]; + } +- // read selects start at index 1 (always have one write port) + for (int p = 0; p < r_total; ++p) { +- row_selects[p + 1] = read_select_nets[p][row]; ++ row_selects[num_write + p] = read_select_nets[p][row]; + } + vector> word_output_nets(r_total); + for (int port = 0; port < r_total; ++port) { +@@ -1481,7 +1662,7 @@ void RamGen::generate(const int mask_size, + row_selects, + shared_select_b_nets, + (word_idx == 0 || column_mux_ratio == 1), +- use_latch_ ? mid_nets : D_nets, ++ use_latch_ ? vector>{mid_nets} : D_nets, + word_output_nets); + } + } +@@ -1625,7 +1806,8 @@ void RamGen::generate(const int mask_size, + "nlat", + latch_cell_, + {{latch_ports_[{PortRoleType::Clock, 0}], clk_b_net}, +- {latch_ports_[{PortRoleType::DataIn, 0}], D_nets[global_bit]}, ++ {latch_ports_[{PortRoleType::DataIn, 0}], ++ D_nets[0][global_bit]}, + {latch_ports_[{PortRoleType::DataOut, 0}], + mid_nets[global_bit]}}); + ram_grid_.addCell(std::move(nl_cell), c); +@@ -1648,13 +1830,16 @@ void RamGen::generate(const int mask_size, + for (int bit = 0; bit < mask_size; ++bit) { + int bit_idx = bit + slice * mask_size; + auto buffer_grid_cell = std::make_unique(); +- makeInst(buffer_grid_cell.get(), +- "buffer", +- fmt::format("in[{}]", bit_idx), +- buffer_cell_, +- {{buffer_ports_[{PortRoleType::DataIn, 0}], +- data_inputs_[bit_idx]->getNet()}, +- {buffer_ports_[{PortRoleType::DataOut, 0}], D_nets[bit_idx]}}); ++ for (int w = 0; w < num_write; ++w) { ++ makeInst(buffer_grid_cell.get(), ++ num_write == 1 ? "buffer" : fmt::format("buffer{}", w), ++ fmt::format("in[{}]", bit_idx), ++ buffer_cell_, ++ {{buffer_ports_[{PortRoleType::DataIn, 0}], ++ data_inputs[w][bit_idx]->getNet()}, ++ {buffer_ports_[{PortRoleType::DataOut, 0}], ++ D_nets[w][bit_idx]}}); ++ } + int buf_col = slice * (mask_size * column_mux_ratio + column_mux_ratio) + + bit * column_mux_ratio; + ram_grid_.addCell(std::move(buffer_grid_cell), buf_col); +@@ -1936,8 +2121,16 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + std::string module_name = fmt::format("RAM{}x{}", num_words, word_size_bit); + + int r_total = rw_ports + r_ports; ++ const int num_write = rw_ports + w_ports; ++ // a write port's bus: D, we, addr_w, or with more than one D0, we0, ... ++ auto wbus = [num_write](const char* base, int w) { ++ return num_write == 1 ? std::string(base) : fmt::format("{}{}", base, w); ++ }; + // Build port list +- std::string port_list = "\n clk,\n D"; ++ std::string port_list = "\n clk"; ++ for (int w = 0; w < num_write; ++w) { ++ port_list += ",\n " + wbus("D", w); ++ } + for (int i = 0; i < r_total; i++) { + if (r_total == 1) { + port_list += ",\n Q"; +@@ -1948,13 +2141,17 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + // address ports + if (rw_ports > 0) { + port_list += ",\n addr_rw"; +- } else if (w_ports > 0) { +- port_list += ",\n addr_w"; ++ } else { ++ for (int w = 0; w < w_ports; ++w) { ++ port_list += ",\n " + wbus("addr_w", w); ++ } + } + for (int i = 0; i < r_ports; i++) { + port_list += fmt::format(",\n addr_r{}", i); + } +- port_list += ",\n we"; ++ for (int w = 0; w < num_write; ++w) { ++ port_list += ",\n " + wbus("we", w); ++ } + + // Build output declarations + std::string output_declaration; +@@ -1973,9 +2170,11 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + if (rw_ports > 0) { + addr_declarations + += fmt::format(" input [{}:0] addr_rw;\n", address_width - 1); +- } else if (w_ports > 0) { +- addr_declarations +- += fmt::format(" input [{}:0] addr_w;\n", address_width - 1); ++ } else { ++ for (int w = 0; w < w_ports; ++w) { ++ addr_declarations += fmt::format( ++ " input [{}:0] {};\n", address_width - 1, wbus("addr_w", w)); ++ } + } + for (int i = 0; i < r_ports; i++) { + addr_declarations +@@ -2005,26 +2204,45 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + addr_name); + } + +- std::string write_addr = (rw_ports > 0) ? "addr_rw" : "addr_w"; ++ // Write logic, the ports in order: where two write the same word in a ++ // cycle, the last one's data is kept. ++ std::string data_declarations; ++ std::string enable_declarations; ++ std::string write_logic; ++ for (int w = 0; w < num_write; ++w) { ++ const std::string write_addr ++ = rw_ports > 0 ? std::string("addr_rw") : wbus("addr_w", w); ++ data_declarations += fmt::format( ++ " input [{}:0] {};\n", word_size_bit - 1, wbus("D", w)); ++ enable_declarations += fmt::format( ++ " input [{}:0] {};\n", slices_per_word - 1, wbus("we", w)); ++ write_logic += fmt::format(R"( for (i = 0; i < {}; i = i + 1) begin ++ if ({}[i]) begin ++ mem[{}][i*{} +:{}] <= {}[i*{} +:{}]; ++ end ++ end ++)", ++ slices_per_word, ++ wbus("we", w), ++ write_addr, ++ mask_size, ++ mask_size, ++ wbus("D", w), ++ mask_size, ++ mask_size); ++ } + + std::string verilog_code = fmt::format(R"(module {} ({} + ); + input clk; +- input [{}:0] D; +-{}{} input [{}:0] we; +- ++{}{}{}{} + // memory array declaration + reg [{}:0] mem[0:{}]; + + // write logic + integer i; + always @(posedge clk) begin +- for (i = 0; i < {}; i = i + 1) begin +- if (we[i]) begin +- mem[{}][i*{} +:{}] <= D[i*{} +:{}]; +- end +- end +- end ++{} end + + // read logic + {} +@@ -2032,18 +2250,13 @@ endmodule + )", + module_name, + port_list, +- word_size_bit - 1, ++ data_declarations, + output_declaration, + addr_declarations, +- slices_per_word - 1, ++ enable_declarations, + word_size_bit - 1, + num_words - 1, +- slices_per_word, +- write_addr, +- mask_size, +- mask_size, +- mask_size, +- mask_size, ++ write_logic, + read_port_logic); + + std::ofstream vf(filename); +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 505b551342..6ca3a68023 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -87,8 +87,12 @@ proc generate_ram_netlist { args } { + set rw_ports 1 + } + +- if { $rw_ports + $w_ports != 1 } { +- utl::error RAM 30 "Must have exactly one read/write port or one write port." ++ if { $rw_ports + $w_ports < 1 } { ++ utl::error RAM 30 "Must have a read/write port or a write port." ++ } ++ ++ if { $rw_ports > 1 || ($rw_ports > 0 && $w_ports > 0) } { ++ utl::error RAM 53 "A read/write port is the only write port." + } + + if { $rw_ports + $r_ports < 1 } { +@@ -100,6 +104,16 @@ proc generate_ram_netlist { args } { + set use_latch $keys(-use_latch) + } + ++ # More than one write port: each has its own address decoder and its ++ # own data, a word written by two in a cycle keeps the last one's. ++ if { $w_ports > 1 && $use_latch } { ++ utl::error RAM 54 "More than one write port is not supported with -use_latch." ++ } ++ if { $w_ports > 1 && $column_mux_ratio > 1 } { ++ utl::error RAM 55 "More than one write port is not supported with\ ++ -column_mux_ratio above 1." ++ } ++ + set tapcell "" + set max_tap_dist 0 + if { [info exists keys(-tapcell)] } { +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 2e4ff86aba..cec5372c33 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_7x7_1r2w_nangate45", + "generate_regfile_asap7", + "generate_regfile_clock_gate_asap7", + "generate_regfile_modes_asap7", +@@ -90,6 +91,12 @@ filegroup( + "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ + "generate_regfile_asap7.regfile", + ], ++ "make_7x7_1r2w_nangate45": [ ++ "make_7x7_1r2w_nangate45_behavioral.vok", ++ "Nangate45/Nangate45.lef", ++ "Nangate45/Nangate45_tech.lef", ++ "Nangate45/Nangate45_typ.lib", ++ ], + "make_7x7_2r1w_nangate45": [ + "make_7x7_2r1w_nangate45_behavioral.vok", + "Nangate45/Nangate45.lef", +diff --git a/src/ram/test/make_7x7_1r2w_nangate45.defok b/src/ram/test/make_7x7_1r2w_nangate45.defok +new file mode 100644 +index 0000000000..b890d9ff4f +--- /dev/null ++++ b/src/ram/test/make_7x7_1r2w_nangate45.defok +@@ -0,0 +1,4402 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM7x7 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 5757 1120 ) ; ++ROW RAM_ROW0 FreePDK45_38x28_10R_NP_162NW_34O 0 0 N DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW1 FreePDK45_38x28_10R_NP_162NW_34O 0 140 FS DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW2 FreePDK45_38x28_10R_NP_162NW_34O 0 280 N DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW3 FreePDK45_38x28_10R_NP_162NW_34O 0 420 FS DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW4 FreePDK45_38x28_10R_NP_162NW_34O 0 560 N DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW5 FreePDK45_38x28_10R_NP_162NW_34O 0 700 FS DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW6 FreePDK45_38x28_10R_NP_162NW_34O 0 840 N DO 303 BY 1 STEP 19 0 ; ++ROW RAM_ROW7 FreePDK45_38x28_10R_NP_162NW_34O 0 980 FS DO 303 BY 1 STEP 19 0 ; ++TRACKS X 9 DO 411 STEP 14 LAYER metal1 ; ++TRACKS Y 7 DO 80 STEP 14 LAYER metal1 ; ++TRACKS X 9 DO 303 STEP 19 LAYER metal2 ; ++TRACKS Y 7 DO 59 STEP 19 LAYER metal2 ; ++TRACKS X 9 DO 411 STEP 14 LAYER metal3 ; ++TRACKS Y 7 DO 80 STEP 14 LAYER metal3 ; ++TRACKS X 9 DO 206 STEP 28 LAYER metal4 ; ++TRACKS Y 7 DO 40 STEP 28 LAYER metal4 ; ++TRACKS X 9 DO 206 STEP 28 LAYER metal5 ; ++TRACKS Y 7 DO 40 STEP 28 LAYER metal5 ; ++TRACKS X 9 DO 206 STEP 28 LAYER metal6 ; ++TRACKS Y 7 DO 40 STEP 28 LAYER metal6 ; ++TRACKS X 89 DO 71 STEP 80 LAYER metal7 ; ++TRACKS Y 87 DO 13 STEP 80 LAYER metal7 ; ++TRACKS X 89 DO 71 STEP 80 LAYER metal8 ; ++TRACKS Y 87 DO 13 STEP 80 LAYER metal8 ; ++TRACKS X 169 DO 35 STEP 160 LAYER metal9 ; ++TRACKS Y 167 DO 6 STEP 160 LAYER metal9 ; ++TRACKS X 169 DO 35 STEP 160 LAYER metal10 ; ++TRACKS Y 167 DO 6 STEP 160 LAYER metal10 ; ++GCELLGRID X 0 DO 20 STEP 285 ; ++GCELLGRID Y 0 DO 3 STEP 285 ; ++VIAS 3 ; ++ - via1_2_280_160_1_1_300_300 + VIARULE Via1Array-0 + CUTSIZE 7 7 + LAYERS metal1 via1 metal2 + CUTSPACING 8 8 + ENCLOSURE 3 0 3 3 ; ++ - via2_3_280_160_1_1_320_320 + VIARULE Via2Array-0 + CUTSIZE 7 7 + LAYERS metal2 via2 metal3 + CUTSPACING 9 9 + ENCLOSURE 3 3 3 3 ; ++ - via3_4_280_160_1_1_320_320 + VIARULE Via3Array-0 + CUTSIZE 7 7 + LAYERS metal3 via3 metal4 + CUTSPACING 9 9 + ENCLOSURE 3 3 3 3 ; ++END VIAS ++COMPONENTS 448 ; ++ - FILLER_1_301 FILLCELL_X2 + SOURCE DIST + PLACED ( 5719 140 ) FS ; ++ - FILLER_3_301 FILLCELL_X2 + SOURCE DIST + PLACED ( 5719 420 ) FS ; ++ - FILLER_5_301 FILLCELL_X2 + SOURCE DIST + PLACED ( 5719 700 ) FS ; ++ - FILLER_6_299 FILLCELL_X4 + SOURCE DIST + PLACED ( 5681 840 ) N ; ++ - FILLER_7_106 FILLCELL_X8 + SOURCE DIST + PLACED ( 2014 980 ) FS ; ++ - FILLER_7_114 FILLCELL_X8 + SOURCE DIST + PLACED ( 2166 980 ) FS ; ++ - FILLER_7_122 FILLCELL_X8 + SOURCE DIST + PLACED ( 2318 980 ) FS ; ++ - FILLER_7_130 FILLCELL_X2 + SOURCE DIST + PLACED ( 2470 980 ) FS ; ++ - FILLER_7_139 FILLCELL_X8 + SOURCE DIST + PLACED ( 2641 980 ) FS ; ++ - FILLER_7_147 FILLCELL_X8 + SOURCE DIST + PLACED ( 2793 980 ) FS ; ++ - FILLER_7_15 FILLCELL_X8 + SOURCE DIST + PLACED ( 285 980 ) FS ; ++ - FILLER_7_155 FILLCELL_X8 + SOURCE DIST + PLACED ( 2945 980 ) FS ; ++ - FILLER_7_163 FILLCELL_X2 + SOURCE DIST + PLACED ( 3097 980 ) FS ; ++ - FILLER_7_172 FILLCELL_X8 + SOURCE DIST + PLACED ( 3268 980 ) FS ; ++ - FILLER_7_180 FILLCELL_X8 + SOURCE DIST + PLACED ( 3420 980 ) FS ; ++ - FILLER_7_188 FILLCELL_X8 + SOURCE DIST + PLACED ( 3572 980 ) FS ; ++ - FILLER_7_196 FILLCELL_X2 + SOURCE DIST + PLACED ( 3724 980 ) FS ; ++ - FILLER_7_205 FILLCELL_X8 + SOURCE DIST + PLACED ( 3895 980 ) FS ; ++ - FILLER_7_213 FILLCELL_X8 + SOURCE DIST + PLACED ( 4047 980 ) FS ; ++ - FILLER_7_221 FILLCELL_X8 + SOURCE DIST + PLACED ( 4199 980 ) FS ; ++ - FILLER_7_229 FILLCELL_X2 + SOURCE DIST + PLACED ( 4351 980 ) FS ; ++ - FILLER_7_23 FILLCELL_X8 + SOURCE DIST + PLACED ( 437 980 ) FS ; ++ - FILLER_7_232 FILLCELL_X8 + SOURCE DIST + PLACED ( 4408 980 ) FS ; ++ - FILLER_7_240 FILLCELL_X8 + SOURCE DIST + PLACED ( 4560 980 ) FS ; ++ - FILLER_7_248 FILLCELL_X8 + SOURCE DIST + PLACED ( 4712 980 ) FS ; ++ - FILLER_7_256 FILLCELL_X8 + SOURCE DIST + PLACED ( 4864 980 ) FS ; ++ - FILLER_7_264 FILLCELL_X8 + SOURCE DIST + PLACED ( 5016 980 ) FS ; ++ - FILLER_7_272 FILLCELL_X4 + SOURCE DIST + PLACED ( 5168 980 ) FS ; ++ - FILLER_7_276 FILLCELL_X2 + SOURCE DIST + PLACED ( 5244 980 ) FS ; ++ - FILLER_7_278 FILLCELL_X1 + SOURCE DIST + PLACED ( 5282 980 ) FS ; ++ - FILLER_7_280 FILLCELL_X8 + SOURCE DIST + PLACED ( 5320 980 ) FS ; ++ - FILLER_7_288 FILLCELL_X8 + SOURCE DIST + PLACED ( 5472 980 ) FS ; ++ - FILLER_7_296 FILLCELL_X4 + SOURCE DIST + PLACED ( 5624 980 ) FS ; ++ - FILLER_7_300 FILLCELL_X2 + SOURCE DIST + PLACED ( 5700 980 ) FS ; ++ - FILLER_7_302 FILLCELL_X1 + SOURCE DIST + PLACED ( 5738 980 ) FS ; ++ - FILLER_7_31 FILLCELL_X2 + SOURCE DIST + PLACED ( 589 980 ) FS ; ++ - FILLER_7_40 FILLCELL_X8 + SOURCE DIST + PLACED ( 760 980 ) FS ; ++ - FILLER_7_48 FILLCELL_X8 + SOURCE DIST + PLACED ( 912 980 ) FS ; ++ - FILLER_7_56 FILLCELL_X8 + SOURCE DIST + PLACED ( 1064 980 ) FS ; ++ - FILLER_7_64 FILLCELL_X2 + SOURCE DIST + PLACED ( 1216 980 ) FS ; ++ - FILLER_7_7 FILLCELL_X8 + SOURCE DIST + PLACED ( 133 980 ) FS ; ++ - FILLER_7_73 FILLCELL_X8 + SOURCE DIST + PLACED ( 1387 980 ) FS ; ++ - FILLER_7_81 FILLCELL_X8 + SOURCE DIST + PLACED ( 1539 980 ) FS ; ++ - FILLER_7_89 FILLCELL_X8 + SOURCE DIST + PLACED ( 1691 980 ) FS ; ++ - FILLER_7_97 FILLCELL_X2 + SOURCE DIST + PLACED ( 1843 980 ) FS ; ++ - buffer0.in[0] BUF_X1 + PLACED ( 19 980 ) FS ; ++ - buffer0.in[1] BUF_X1 + PLACED ( 646 980 ) FS ; ++ - buffer0.in[2] BUF_X1 + PLACED ( 1273 980 ) FS ; ++ - buffer0.in[3] BUF_X1 + PLACED ( 1900 980 ) FS ; ++ - buffer0.in[4] BUF_X1 + PLACED ( 2527 980 ) FS ; ++ - buffer0.in[5] BUF_X1 + PLACED ( 3154 980 ) FS ; ++ - buffer0.in[6] BUF_X1 + PLACED ( 3781 980 ) FS ; ++ - buffer1.in[0] BUF_X1 + PLACED ( 76 980 ) FS ; ++ - buffer1.in[1] BUF_X1 + PLACED ( 703 980 ) FS ; ++ - buffer1.in[2] BUF_X1 + PLACED ( 1330 980 ) FS ; ++ - buffer1.in[3] BUF_X1 + PLACED ( 1957 980 ) FS ; ++ - buffer1.in[4] BUF_X1 + PLACED ( 2584 980 ) FS ; ++ - buffer1.in[5] BUF_X1 + PLACED ( 3211 980 ) FS ; ++ - buffer1.in[6] BUF_X1 + PLACED ( 3838 980 ) FS ; ++ - decoder_p0.and_layer0_word0 AND2_X1 + PLACED ( 5092 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2_X1 + PLACED ( 5092 140 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2_X1 + PLACED ( 5092 280 ) N ; ++ - decoder_p0.and_layer0_word3 AND2_X1 + PLACED ( 5092 420 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2_X1 + PLACED ( 5092 560 ) N ; ++ - decoder_p0.and_layer0_word5 AND2_X1 + PLACED ( 5092 700 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2_X1 + PLACED ( 5092 840 ) N ; ++ - decoder_p0.and_layer1_word0 AND2_X1 + PLACED ( 5168 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2_X1 + PLACED ( 5168 140 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2_X1 + PLACED ( 5168 280 ) N ; ++ - decoder_p0.and_layer1_word3 AND2_X1 + PLACED ( 5168 420 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2_X1 + PLACED ( 5168 560 ) N ; ++ - decoder_p0.and_layer1_word5 AND2_X1 + PLACED ( 5168 700 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2_X1 + PLACED ( 5168 840 ) N ; ++ - decoder_p0.inv_p0_a0 INV_X1 + PLACED ( 5681 560 ) N ; ++ - decoder_p0.inv_p0_a1 INV_X1 + PLACED ( 5681 280 ) N ; ++ - decoder_p0.inv_p0_a2 INV_X1 + PLACED ( 5681 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2_X1 + PLACED ( 5320 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2_X1 + PLACED ( 5320 140 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2_X1 + PLACED ( 5320 280 ) N ; ++ - decoder_p1.and_layer0_word3 AND2_X1 + PLACED ( 5320 420 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2_X1 + PLACED ( 5320 560 ) N ; ++ - decoder_p1.and_layer0_word5 AND2_X1 + PLACED ( 5320 700 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2_X1 + PLACED ( 5320 840 ) N ; ++ - decoder_p1.and_layer1_word0 AND2_X1 + PLACED ( 5396 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2_X1 + PLACED ( 5396 140 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2_X1 + PLACED ( 5396 280 ) N ; ++ - decoder_p1.and_layer1_word3 AND2_X1 + PLACED ( 5396 420 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2_X1 + PLACED ( 5396 560 ) N ; ++ - decoder_p1.and_layer1_word5 AND2_X1 + PLACED ( 5396 700 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2_X1 + PLACED ( 5396 840 ) N ; ++ - decoder_p1.inv_p1_a0 INV_X1 + PLACED ( 5681 700 ) FS ; ++ - decoder_p1.inv_p1_a1 INV_X1 + PLACED ( 5681 420 ) FS ; ++ - decoder_p1.inv_p1_a2 INV_X1 + PLACED ( 5681 140 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2_X1 + PLACED ( 5529 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2_X1 + PLACED ( 5529 140 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2_X1 + PLACED ( 5529 280 ) N ; ++ - decoder_p2.and_layer0_word3 AND2_X1 + PLACED ( 5529 420 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2_X1 + PLACED ( 5529 560 ) N ; ++ - decoder_p2.and_layer0_word5 AND2_X1 + PLACED ( 5529 700 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2_X1 + PLACED ( 5529 840 ) N ; ++ - decoder_p2.and_layer1_word0 AND2_X1 + PLACED ( 5605 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2_X1 + PLACED ( 5605 140 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2_X1 + PLACED ( 5605 280 ) N ; ++ - decoder_p2.and_layer1_word3 AND2_X1 + PLACED ( 5605 420 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2_X1 + PLACED ( 5605 560 ) N ; ++ - decoder_p2.and_layer1_word5 AND2_X1 + PLACED ( 5605 700 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2_X1 + PLACED ( 5605 840 ) N ; ++ - decoder_p2.inv_p2_a0 INV_X1 + PLACED ( 5719 560 ) N ; ++ - decoder_p2.inv_p2_a1 INV_X1 + PLACED ( 5719 280 ) N ; ++ - decoder_p2.inv_p2_a2 INV_X1 + PLACED ( 5719 0 ) N ; ++ - sel_buf_r_p2.sel_buf_0 BUF_X1 + PLACED ( 5472 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 BUF_X1 + PLACED ( 5472 140 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 BUF_X1 + PLACED ( 5472 280 ) N ; ++ - sel_buf_r_p2.sel_buf_3 BUF_X1 + PLACED ( 5472 420 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 BUF_X1 + PLACED ( 5472 560 ) N ; ++ - sel_buf_r_p2.sel_buf_5 BUF_X1 + PLACED ( 5472 700 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 BUF_X1 + PLACED ( 5472 840 ) N ; ++ - sel_buf_w_p0.sel_buf_0 BUF_X1 + PLACED ( 5035 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 BUF_X1 + PLACED ( 5035 140 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 BUF_X1 + PLACED ( 5035 280 ) N ; ++ - sel_buf_w_p0.sel_buf_3 BUF_X1 + PLACED ( 5035 420 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 BUF_X1 + PLACED ( 5035 560 ) N ; ++ - sel_buf_w_p0.sel_buf_5 BUF_X1 + PLACED ( 5035 700 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 BUF_X1 + PLACED ( 5035 840 ) N ; ++ - sel_buf_w_p1.sel_buf_0 BUF_X1 + PLACED ( 5244 0 ) N ; ++ - sel_buf_w_p1.sel_buf_1 BUF_X1 + PLACED ( 5244 140 ) FS ; ++ - sel_buf_w_p1.sel_buf_2 BUF_X1 + PLACED ( 5244 280 ) N ; ++ - sel_buf_w_p1.sel_buf_3 BUF_X1 + PLACED ( 5244 420 ) FS ; ++ - sel_buf_w_p1.sel_buf_4 BUF_X1 + PLACED ( 5244 560 ) N ; ++ - sel_buf_w_p1.sel_buf_5 BUF_X1 + PLACED ( 5244 700 ) FS ; ++ - sel_buf_w_p1.sel_buf_6 BUF_X1 + PLACED ( 5244 840 ) N ; ++ - storage_0_0_0.any_or0 OR2_X1 + PLACED ( 4674 0 ) N ; ++ - storage_0_0_0.bit0.bit DFF_X1 + PLACED ( 19 0 ) N ; ++ - storage_0_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 0 ) N ; ++ - storage_0_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 0 ) N ; ++ - storage_0_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 0 ) N ; ++ - storage_0_0_0.bit1.bit DFF_X1 + PLACED ( 646 0 ) N ; ++ - storage_0_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 0 ) N ; ++ - storage_0_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 0 ) N ; ++ - storage_0_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 0 ) N ; ++ - storage_0_0_0.bit2.bit DFF_X1 + PLACED ( 1273 0 ) N ; ++ - storage_0_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 0 ) N ; ++ - storage_0_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 0 ) N ; ++ - storage_0_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 0 ) N ; ++ - storage_0_0_0.bit3.bit DFF_X1 + PLACED ( 1900 0 ) N ; ++ - storage_0_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 0 ) N ; ++ - storage_0_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 0 ) N ; ++ - storage_0_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 0 ) N ; ++ - storage_0_0_0.bit4.bit DFF_X1 + PLACED ( 2527 0 ) N ; ++ - storage_0_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 0 ) N ; ++ - storage_0_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 0 ) N ; ++ - storage_0_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 0 ) N ; ++ - storage_0_0_0.bit5.bit DFF_X1 + PLACED ( 3154 0 ) N ; ++ - storage_0_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 0 ) N ; ++ - storage_0_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 0 ) N ; ++ - storage_0_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 0 ) N ; ++ - storage_0_0_0.bit6.bit DFF_X1 + PLACED ( 3781 0 ) N ; ++ - storage_0_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 0 ) N ; ++ - storage_0_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 0 ) N ; ++ - storage_0_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 0 ) N ; ++ - storage_0_0_0.cg CLKGATE_X1 + PLACED ( 4750 0 ) N ; ++ - storage_0_0_0.gcand0 AND2_X1 + PLACED ( 4408 0 ) N ; ++ - storage_0_0_0.gcand1 AND2_X1 + PLACED ( 4484 0 ) N ; ++ - storage_0_0_0.later_inv0 INV_X1 + PLACED ( 4560 0 ) N ; ++ - storage_0_0_0.select_inv_0 INV_X1 + PLACED ( 4997 0 ) N ; ++ - storage_0_0_0.take_and0 AND2_X1 + PLACED ( 4598 0 ) N ; ++ - storage_1_0_0.any_or0 OR2_X1 + PLACED ( 4674 140 ) FS ; ++ - storage_1_0_0.bit0.bit DFF_X1 + PLACED ( 19 140 ) FS ; ++ - storage_1_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 140 ) FS ; ++ - storage_1_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 140 ) FS ; ++ - storage_1_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 140 ) FS ; ++ - storage_1_0_0.bit1.bit DFF_X1 + PLACED ( 646 140 ) FS ; ++ - storage_1_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 140 ) FS ; ++ - storage_1_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 140 ) FS ; ++ - storage_1_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 140 ) FS ; ++ - storage_1_0_0.bit2.bit DFF_X1 + PLACED ( 1273 140 ) FS ; ++ - storage_1_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 140 ) FS ; ++ - storage_1_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 140 ) FS ; ++ - storage_1_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 140 ) FS ; ++ - storage_1_0_0.bit3.bit DFF_X1 + PLACED ( 1900 140 ) FS ; ++ - storage_1_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 140 ) FS ; ++ - storage_1_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 140 ) FS ; ++ - storage_1_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 140 ) FS ; ++ - storage_1_0_0.bit4.bit DFF_X1 + PLACED ( 2527 140 ) FS ; ++ - storage_1_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 140 ) FS ; ++ - storage_1_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 140 ) FS ; ++ - storage_1_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 140 ) FS ; ++ - storage_1_0_0.bit5.bit DFF_X1 + PLACED ( 3154 140 ) FS ; ++ - storage_1_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 140 ) FS ; ++ - storage_1_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 140 ) FS ; ++ - storage_1_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 140 ) FS ; ++ - storage_1_0_0.bit6.bit DFF_X1 + PLACED ( 3781 140 ) FS ; ++ - storage_1_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 140 ) FS ; ++ - storage_1_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 140 ) FS ; ++ - storage_1_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 140 ) FS ; ++ - storage_1_0_0.cg CLKGATE_X1 + PLACED ( 4750 140 ) FS ; ++ - storage_1_0_0.gcand0 AND2_X1 + PLACED ( 4408 140 ) FS ; ++ - storage_1_0_0.gcand1 AND2_X1 + PLACED ( 4484 140 ) FS ; ++ - storage_1_0_0.later_inv0 INV_X1 + PLACED ( 4560 140 ) FS ; ++ - storage_1_0_0.select_inv_0 INV_X1 + PLACED ( 4997 140 ) FS ; ++ - storage_1_0_0.take_and0 AND2_X1 + PLACED ( 4598 140 ) FS ; ++ - storage_2_0_0.any_or0 OR2_X1 + PLACED ( 4674 280 ) N ; ++ - storage_2_0_0.bit0.bit DFF_X1 + PLACED ( 19 280 ) N ; ++ - storage_2_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 280 ) N ; ++ - storage_2_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 280 ) N ; ++ - storage_2_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 280 ) N ; ++ - storage_2_0_0.bit1.bit DFF_X1 + PLACED ( 646 280 ) N ; ++ - storage_2_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 280 ) N ; ++ - storage_2_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 280 ) N ; ++ - storage_2_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 280 ) N ; ++ - storage_2_0_0.bit2.bit DFF_X1 + PLACED ( 1273 280 ) N ; ++ - storage_2_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 280 ) N ; ++ - storage_2_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 280 ) N ; ++ - storage_2_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 280 ) N ; ++ - storage_2_0_0.bit3.bit DFF_X1 + PLACED ( 1900 280 ) N ; ++ - storage_2_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 280 ) N ; ++ - storage_2_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 280 ) N ; ++ - storage_2_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 280 ) N ; ++ - storage_2_0_0.bit4.bit DFF_X1 + PLACED ( 2527 280 ) N ; ++ - storage_2_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 280 ) N ; ++ - storage_2_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 280 ) N ; ++ - storage_2_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 280 ) N ; ++ - storage_2_0_0.bit5.bit DFF_X1 + PLACED ( 3154 280 ) N ; ++ - storage_2_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 280 ) N ; ++ - storage_2_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 280 ) N ; ++ - storage_2_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 280 ) N ; ++ - storage_2_0_0.bit6.bit DFF_X1 + PLACED ( 3781 280 ) N ; ++ - storage_2_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 280 ) N ; ++ - storage_2_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 280 ) N ; ++ - storage_2_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 280 ) N ; ++ - storage_2_0_0.cg CLKGATE_X1 + PLACED ( 4750 280 ) N ; ++ - storage_2_0_0.gcand0 AND2_X1 + PLACED ( 4408 280 ) N ; ++ - storage_2_0_0.gcand1 AND2_X1 + PLACED ( 4484 280 ) N ; ++ - storage_2_0_0.later_inv0 INV_X1 + PLACED ( 4560 280 ) N ; ++ - storage_2_0_0.select_inv_0 INV_X1 + PLACED ( 4997 280 ) N ; ++ - storage_2_0_0.take_and0 AND2_X1 + PLACED ( 4598 280 ) N ; ++ - storage_3_0_0.any_or0 OR2_X1 + PLACED ( 4674 420 ) FS ; ++ - storage_3_0_0.bit0.bit DFF_X1 + PLACED ( 19 420 ) FS ; ++ - storage_3_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 420 ) FS ; ++ - storage_3_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 420 ) FS ; ++ - storage_3_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 420 ) FS ; ++ - storage_3_0_0.bit1.bit DFF_X1 + PLACED ( 646 420 ) FS ; ++ - storage_3_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 420 ) FS ; ++ - storage_3_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 420 ) FS ; ++ - storage_3_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 420 ) FS ; ++ - storage_3_0_0.bit2.bit DFF_X1 + PLACED ( 1273 420 ) FS ; ++ - storage_3_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 420 ) FS ; ++ - storage_3_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 420 ) FS ; ++ - storage_3_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 420 ) FS ; ++ - storage_3_0_0.bit3.bit DFF_X1 + PLACED ( 1900 420 ) FS ; ++ - storage_3_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 420 ) FS ; ++ - storage_3_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 420 ) FS ; ++ - storage_3_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 420 ) FS ; ++ - storage_3_0_0.bit4.bit DFF_X1 + PLACED ( 2527 420 ) FS ; ++ - storage_3_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 420 ) FS ; ++ - storage_3_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 420 ) FS ; ++ - storage_3_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 420 ) FS ; ++ - storage_3_0_0.bit5.bit DFF_X1 + PLACED ( 3154 420 ) FS ; ++ - storage_3_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 420 ) FS ; ++ - storage_3_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 420 ) FS ; ++ - storage_3_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 420 ) FS ; ++ - storage_3_0_0.bit6.bit DFF_X1 + PLACED ( 3781 420 ) FS ; ++ - storage_3_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 420 ) FS ; ++ - storage_3_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 420 ) FS ; ++ - storage_3_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 420 ) FS ; ++ - storage_3_0_0.cg CLKGATE_X1 + PLACED ( 4750 420 ) FS ; ++ - storage_3_0_0.gcand0 AND2_X1 + PLACED ( 4408 420 ) FS ; ++ - storage_3_0_0.gcand1 AND2_X1 + PLACED ( 4484 420 ) FS ; ++ - storage_3_0_0.later_inv0 INV_X1 + PLACED ( 4560 420 ) FS ; ++ - storage_3_0_0.select_inv_0 INV_X1 + PLACED ( 4997 420 ) FS ; ++ - storage_3_0_0.take_and0 AND2_X1 + PLACED ( 4598 420 ) FS ; ++ - storage_4_0_0.any_or0 OR2_X1 + PLACED ( 4674 560 ) N ; ++ - storage_4_0_0.bit0.bit DFF_X1 + PLACED ( 19 560 ) N ; ++ - storage_4_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 560 ) N ; ++ - storage_4_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 560 ) N ; ++ - storage_4_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 560 ) N ; ++ - storage_4_0_0.bit1.bit DFF_X1 + PLACED ( 646 560 ) N ; ++ - storage_4_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 560 ) N ; ++ - storage_4_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 560 ) N ; ++ - storage_4_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 560 ) N ; ++ - storage_4_0_0.bit2.bit DFF_X1 + PLACED ( 1273 560 ) N ; ++ - storage_4_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 560 ) N ; ++ - storage_4_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 560 ) N ; ++ - storage_4_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 560 ) N ; ++ - storage_4_0_0.bit3.bit DFF_X1 + PLACED ( 1900 560 ) N ; ++ - storage_4_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 560 ) N ; ++ - storage_4_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 560 ) N ; ++ - storage_4_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 560 ) N ; ++ - storage_4_0_0.bit4.bit DFF_X1 + PLACED ( 2527 560 ) N ; ++ - storage_4_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 560 ) N ; ++ - storage_4_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 560 ) N ; ++ - storage_4_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 560 ) N ; ++ - storage_4_0_0.bit5.bit DFF_X1 + PLACED ( 3154 560 ) N ; ++ - storage_4_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 560 ) N ; ++ - storage_4_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 560 ) N ; ++ - storage_4_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 560 ) N ; ++ - storage_4_0_0.bit6.bit DFF_X1 + PLACED ( 3781 560 ) N ; ++ - storage_4_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 560 ) N ; ++ - storage_4_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 560 ) N ; ++ - storage_4_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 560 ) N ; ++ - storage_4_0_0.cg CLKGATE_X1 + PLACED ( 4750 560 ) N ; ++ - storage_4_0_0.gcand0 AND2_X1 + PLACED ( 4408 560 ) N ; ++ - storage_4_0_0.gcand1 AND2_X1 + PLACED ( 4484 560 ) N ; ++ - storage_4_0_0.later_inv0 INV_X1 + PLACED ( 4560 560 ) N ; ++ - storage_4_0_0.select_inv_0 INV_X1 + PLACED ( 4997 560 ) N ; ++ - storage_4_0_0.take_and0 AND2_X1 + PLACED ( 4598 560 ) N ; ++ - storage_5_0_0.any_or0 OR2_X1 + PLACED ( 4674 700 ) FS ; ++ - storage_5_0_0.bit0.bit DFF_X1 + PLACED ( 19 700 ) FS ; ++ - storage_5_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 700 ) FS ; ++ - storage_5_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 700 ) FS ; ++ - storage_5_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 700 ) FS ; ++ - storage_5_0_0.bit1.bit DFF_X1 + PLACED ( 646 700 ) FS ; ++ - storage_5_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 700 ) FS ; ++ - storage_5_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 700 ) FS ; ++ - storage_5_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 700 ) FS ; ++ - storage_5_0_0.bit2.bit DFF_X1 + PLACED ( 1273 700 ) FS ; ++ - storage_5_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 700 ) FS ; ++ - storage_5_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 700 ) FS ; ++ - storage_5_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 700 ) FS ; ++ - storage_5_0_0.bit3.bit DFF_X1 + PLACED ( 1900 700 ) FS ; ++ - storage_5_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 700 ) FS ; ++ - storage_5_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 700 ) FS ; ++ - storage_5_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 700 ) FS ; ++ - storage_5_0_0.bit4.bit DFF_X1 + PLACED ( 2527 700 ) FS ; ++ - storage_5_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 700 ) FS ; ++ - storage_5_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 700 ) FS ; ++ - storage_5_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 700 ) FS ; ++ - storage_5_0_0.bit5.bit DFF_X1 + PLACED ( 3154 700 ) FS ; ++ - storage_5_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 700 ) FS ; ++ - storage_5_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 700 ) FS ; ++ - storage_5_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 700 ) FS ; ++ - storage_5_0_0.bit6.bit DFF_X1 + PLACED ( 3781 700 ) FS ; ++ - storage_5_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 700 ) FS ; ++ - storage_5_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 700 ) FS ; ++ - storage_5_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 700 ) FS ; ++ - storage_5_0_0.cg CLKGATE_X1 + PLACED ( 4750 700 ) FS ; ++ - storage_5_0_0.gcand0 AND2_X1 + PLACED ( 4408 700 ) FS ; ++ - storage_5_0_0.gcand1 AND2_X1 + PLACED ( 4484 700 ) FS ; ++ - storage_5_0_0.later_inv0 INV_X1 + PLACED ( 4560 700 ) FS ; ++ - storage_5_0_0.select_inv_0 INV_X1 + PLACED ( 4997 700 ) FS ; ++ - storage_5_0_0.take_and0 AND2_X1 + PLACED ( 4598 700 ) FS ; ++ - storage_6_0_0.any_or0 OR2_X1 + PLACED ( 4674 840 ) N ; ++ - storage_6_0_0.bit0.bit DFF_X1 + PLACED ( 19 840 ) N ; ++ - storage_6_0_0.bit0.dmux0 AOI22_X1 + PLACED ( 494 840 ) N ; ++ - storage_6_0_0.bit0.dmux0_inv INV_X1 + PLACED ( 589 840 ) N ; ++ - storage_6_0_0.bit0.obuf0 TBUF_X1 + PLACED ( 342 840 ) N ; ++ - storage_6_0_0.bit1.bit DFF_X1 + PLACED ( 646 840 ) N ; ++ - storage_6_0_0.bit1.dmux0 AOI22_X1 + PLACED ( 1121 840 ) N ; ++ - storage_6_0_0.bit1.dmux0_inv INV_X1 + PLACED ( 1216 840 ) N ; ++ - storage_6_0_0.bit1.obuf0 TBUF_X1 + PLACED ( 969 840 ) N ; ++ - storage_6_0_0.bit2.bit DFF_X1 + PLACED ( 1273 840 ) N ; ++ - storage_6_0_0.bit2.dmux0 AOI22_X1 + PLACED ( 1748 840 ) N ; ++ - storage_6_0_0.bit2.dmux0_inv INV_X1 + PLACED ( 1843 840 ) N ; ++ - storage_6_0_0.bit2.obuf0 TBUF_X1 + PLACED ( 1596 840 ) N ; ++ - storage_6_0_0.bit3.bit DFF_X1 + PLACED ( 1900 840 ) N ; ++ - storage_6_0_0.bit3.dmux0 AOI22_X1 + PLACED ( 2375 840 ) N ; ++ - storage_6_0_0.bit3.dmux0_inv INV_X1 + PLACED ( 2470 840 ) N ; ++ - storage_6_0_0.bit3.obuf0 TBUF_X1 + PLACED ( 2223 840 ) N ; ++ - storage_6_0_0.bit4.bit DFF_X1 + PLACED ( 2527 840 ) N ; ++ - storage_6_0_0.bit4.dmux0 AOI22_X1 + PLACED ( 3002 840 ) N ; ++ - storage_6_0_0.bit4.dmux0_inv INV_X1 + PLACED ( 3097 840 ) N ; ++ - storage_6_0_0.bit4.obuf0 TBUF_X1 + PLACED ( 2850 840 ) N ; ++ - storage_6_0_0.bit5.bit DFF_X1 + PLACED ( 3154 840 ) N ; ++ - storage_6_0_0.bit5.dmux0 AOI22_X1 + PLACED ( 3629 840 ) N ; ++ - storage_6_0_0.bit5.dmux0_inv INV_X1 + PLACED ( 3724 840 ) N ; ++ - storage_6_0_0.bit5.obuf0 TBUF_X1 + PLACED ( 3477 840 ) N ; ++ - storage_6_0_0.bit6.bit DFF_X1 + PLACED ( 3781 840 ) N ; ++ - storage_6_0_0.bit6.dmux0 AOI22_X1 + PLACED ( 4256 840 ) N ; ++ - storage_6_0_0.bit6.dmux0_inv INV_X1 + PLACED ( 4351 840 ) N ; ++ - storage_6_0_0.bit6.obuf0 TBUF_X1 + PLACED ( 4104 840 ) N ; ++ - storage_6_0_0.cg CLKGATE_X1 + PLACED ( 4750 840 ) N ; ++ - storage_6_0_0.gcand0 AND2_X1 + PLACED ( 4408 840 ) N ; ++ - storage_6_0_0.gcand1 AND2_X1 + PLACED ( 4484 840 ) N ; ++ - storage_6_0_0.later_inv0 INV_X1 + PLACED ( 4560 840 ) N ; ++ - storage_6_0_0.select_inv_0 INV_X1 + PLACED ( 4997 840 ) N ; ++ - storage_6_0_0.take_and0 AND2_X1 + PLACED ( 4598 840 ) N ; ++ - tapcell.cell0_0 TAPCELL_X1 + PLACED ( 0 0 ) N ; ++ - tapcell.cell0_1 TAPCELL_X1 + PLACED ( 0 140 ) FS ; ++ - tapcell.cell0_2 TAPCELL_X1 + PLACED ( 0 280 ) N ; ++ - tapcell.cell0_3 TAPCELL_X1 + PLACED ( 0 420 ) FS ; ++ - tapcell.cell0_4 TAPCELL_X1 + PLACED ( 0 560 ) N ; ++ - tapcell.cell0_5 TAPCELL_X1 + PLACED ( 0 700 ) FS ; ++ - tapcell.cell0_6 TAPCELL_X1 + PLACED ( 0 840 ) N ; ++ - tapcell.cell0_7 TAPCELL_X1 + PLACED ( 0 980 ) FS ; ++ - tapcell.cell1_0 TAPCELL_X1 + PLACED ( 627 0 ) N ; ++ - tapcell.cell1_1 TAPCELL_X1 + PLACED ( 627 140 ) FS ; ++ - tapcell.cell1_2 TAPCELL_X1 + PLACED ( 627 280 ) N ; ++ - tapcell.cell1_3 TAPCELL_X1 + PLACED ( 627 420 ) FS ; ++ - tapcell.cell1_4 TAPCELL_X1 + PLACED ( 627 560 ) N ; ++ - tapcell.cell1_5 TAPCELL_X1 + PLACED ( 627 700 ) FS ; ++ - tapcell.cell1_6 TAPCELL_X1 + PLACED ( 627 840 ) N ; ++ - tapcell.cell1_7 TAPCELL_X1 + PLACED ( 627 980 ) FS ; ++ - tapcell.cell2_0 TAPCELL_X1 + PLACED ( 1254 0 ) N ; ++ - tapcell.cell2_1 TAPCELL_X1 + PLACED ( 1254 140 ) FS ; ++ - tapcell.cell2_2 TAPCELL_X1 + PLACED ( 1254 280 ) N ; ++ - tapcell.cell2_3 TAPCELL_X1 + PLACED ( 1254 420 ) FS ; ++ - tapcell.cell2_4 TAPCELL_X1 + PLACED ( 1254 560 ) N ; ++ - tapcell.cell2_5 TAPCELL_X1 + PLACED ( 1254 700 ) FS ; ++ - tapcell.cell2_6 TAPCELL_X1 + PLACED ( 1254 840 ) N ; ++ - tapcell.cell2_7 TAPCELL_X1 + PLACED ( 1254 980 ) FS ; ++ - tapcell.cell3_0 TAPCELL_X1 + PLACED ( 1881 0 ) N ; ++ - tapcell.cell3_1 TAPCELL_X1 + PLACED ( 1881 140 ) FS ; ++ - tapcell.cell3_2 TAPCELL_X1 + PLACED ( 1881 280 ) N ; ++ - tapcell.cell3_3 TAPCELL_X1 + PLACED ( 1881 420 ) FS ; ++ - tapcell.cell3_4 TAPCELL_X1 + PLACED ( 1881 560 ) N ; ++ - tapcell.cell3_5 TAPCELL_X1 + PLACED ( 1881 700 ) FS ; ++ - tapcell.cell3_6 TAPCELL_X1 + PLACED ( 1881 840 ) N ; ++ - tapcell.cell3_7 TAPCELL_X1 + PLACED ( 1881 980 ) FS ; ++ - tapcell.cell4_0 TAPCELL_X1 + PLACED ( 2508 0 ) N ; ++ - tapcell.cell4_1 TAPCELL_X1 + PLACED ( 2508 140 ) FS ; ++ - tapcell.cell4_2 TAPCELL_X1 + PLACED ( 2508 280 ) N ; ++ - tapcell.cell4_3 TAPCELL_X1 + PLACED ( 2508 420 ) FS ; ++ - tapcell.cell4_4 TAPCELL_X1 + PLACED ( 2508 560 ) N ; ++ - tapcell.cell4_5 TAPCELL_X1 + PLACED ( 2508 700 ) FS ; ++ - tapcell.cell4_6 TAPCELL_X1 + PLACED ( 2508 840 ) N ; ++ - tapcell.cell4_7 TAPCELL_X1 + PLACED ( 2508 980 ) FS ; ++ - tapcell.cell5_0 TAPCELL_X1 + PLACED ( 3135 0 ) N ; ++ - tapcell.cell5_1 TAPCELL_X1 + PLACED ( 3135 140 ) FS ; ++ - tapcell.cell5_2 TAPCELL_X1 + PLACED ( 3135 280 ) N ; ++ - tapcell.cell5_3 TAPCELL_X1 + PLACED ( 3135 420 ) FS ; ++ - tapcell.cell5_4 TAPCELL_X1 + PLACED ( 3135 560 ) N ; ++ - tapcell.cell5_5 TAPCELL_X1 + PLACED ( 3135 700 ) FS ; ++ - tapcell.cell5_6 TAPCELL_X1 + PLACED ( 3135 840 ) N ; ++ - tapcell.cell5_7 TAPCELL_X1 + PLACED ( 3135 980 ) FS ; ++ - tapcell.cell6_0 TAPCELL_X1 + PLACED ( 3762 0 ) N ; ++ - tapcell.cell6_1 TAPCELL_X1 + PLACED ( 3762 140 ) FS ; ++ - tapcell.cell6_2 TAPCELL_X1 + PLACED ( 3762 280 ) N ; ++ - tapcell.cell6_3 TAPCELL_X1 + PLACED ( 3762 420 ) FS ; ++ - tapcell.cell6_4 TAPCELL_X1 + PLACED ( 3762 560 ) N ; ++ - tapcell.cell6_5 TAPCELL_X1 + PLACED ( 3762 700 ) FS ; ++ - tapcell.cell6_6 TAPCELL_X1 + PLACED ( 3762 840 ) N ; ++ - tapcell.cell6_7 TAPCELL_X1 + PLACED ( 3762 980 ) FS ; ++ - tapcell.cell7_0 TAPCELL_X1 + PLACED ( 4389 0 ) N ; ++ - tapcell.cell7_1 TAPCELL_X1 + PLACED ( 4389 140 ) FS ; ++ - tapcell.cell7_2 TAPCELL_X1 + PLACED ( 4389 280 ) N ; ++ - tapcell.cell7_3 TAPCELL_X1 + PLACED ( 4389 420 ) FS ; ++ - tapcell.cell7_4 TAPCELL_X1 + PLACED ( 4389 560 ) N ; ++ - tapcell.cell7_5 TAPCELL_X1 + PLACED ( 4389 700 ) FS ; ++ - tapcell.cell7_6 TAPCELL_X1 + PLACED ( 4389 840 ) N ; ++ - tapcell.cell7_7 TAPCELL_X1 + PLACED ( 4389 980 ) FS ; ++ - tapcell.cell8_0 TAPCELL_X1 + PLACED ( 5301 0 ) N ; ++ - tapcell.cell8_1 TAPCELL_X1 + PLACED ( 5301 140 ) FS ; ++ - tapcell.cell8_2 TAPCELL_X1 + PLACED ( 5301 280 ) N ; ++ - tapcell.cell8_3 TAPCELL_X1 + PLACED ( 5301 420 ) FS ; ++ - tapcell.cell8_4 TAPCELL_X1 + PLACED ( 5301 560 ) N ; ++ - tapcell.cell8_5 TAPCELL_X1 + PLACED ( 5301 700 ) FS ; ++ - tapcell.cell8_6 TAPCELL_X1 + PLACED ( 5301 840 ) N ; ++ - tapcell.cell8_7 TAPCELL_X1 + PLACED ( 5301 980 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D0[0] + NET D0[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 9 1113 ) N ; ++ - D0[1] + NET D0[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 681 1113 ) N ; ++ - D0[2] + NET D0[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 1297 1113 ) N ; ++ - D0[3] + NET D0[3] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 1913 1113 ) N ; ++ - D0[4] + NET D0[4] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 2529 1113 ) N ; ++ - D0[5] + NET D0[5] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 3201 1113 ) N ; ++ - D0[6] + NET D0[6] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 3817 1113 ) N ; ++ - D1[0] + NET D1[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 65 1113 ) N ; ++ - D1[1] + NET D1[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 737 1113 ) N ; ++ - D1[2] + NET D1[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 1409 1113 ) N ; ++ - D1[3] + NET D1[3] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 1969 1113 ) N ; ++ - D1[4] + NET D1[4] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 2585 1113 ) N ; ++ - D1[5] + NET D1[5] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 3257 1113 ) N ; ++ - D1[6] + NET D1[6] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 3873 1113 ) N ; ++ - Q[0] + NET Q[0] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 345 1113 ) N ; ++ - Q[1] + NET Q[1] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 961 1113 ) N ; ++ - Q[2] + NET Q[2] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 1577 1113 ) N ; ++ - Q[3] + NET Q[3] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 2193 1113 ) N ; ++ - Q[4] + NET Q[4] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 2865 1113 ) N ; ++ - Q[5] + NET Q[5] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 3481 1113 ) N ; ++ - Q[6] + NET Q[6] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 4097 1113 ) N ; ++ - VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + LAYER metal4 ( -7 -1113 ) ( 7 -1099 ) ++ + LAYER metal4 ( -907 -7 ) ( -893 7 ) ++ + LAYER metal4 ( -907 -1113 ) ( -893 -1099 ) ++ + LAYER metal4 ( -1807 -7 ) ( -1793 7 ) ++ + LAYER metal4 ( -1807 -1113 ) ( -1793 -1099 ) ++ + LAYER metal4 ( -2707 -7 ) ( -2693 7 ) ++ + LAYER metal4 ( -2707 -1113 ) ( -2693 -1099 ) ++ + LAYER metal4 ( -3607 -7 ) ( -3593 7 ) ++ + LAYER metal4 ( -3607 -1113 ) ( -3593 -1099 ) ++ + LAYER metal4 ( -4507 -7 ) ( -4493 7 ) ++ + LAYER metal4 ( -4507 -1113 ) ( -4493 -1099 ) ++ + LAYER metal1 ( 800 -137 ) ( 807 -129 ) ++ + LAYER metal1 ( -4950 -137 ) ( -4943 -129 ) ++ + LAYER metal1 ( 800 -417 ) ( 807 -409 ) ++ + LAYER metal1 ( -4950 -417 ) ( -4943 -409 ) ++ + LAYER metal1 ( 800 -697 ) ( 807 -689 ) ++ + LAYER metal1 ( -4950 -697 ) ( -4943 -689 ) ++ + LAYER metal1 ( 800 -977 ) ( 807 -969 ) ++ + LAYER metal1 ( -4950 -977 ) ( -4943 -969 ) ++ + FIXED ( 4950 1113 ) N ; ++ - VSS + NET VSS + SPECIAL + DIRECTION INOUT + USE GROUND ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + LAYER metal4 ( -7 -1113 ) ( 7 -1099 ) ++ + LAYER metal4 ( -907 -7 ) ( -893 7 ) ++ + LAYER metal4 ( -907 -1113 ) ( -893 -1099 ) ++ + LAYER metal4 ( -1807 -7 ) ( -1793 7 ) ++ + LAYER metal4 ( -1807 -1113 ) ( -1793 -1099 ) ++ + LAYER metal4 ( -2707 -7 ) ( -2693 7 ) ++ + LAYER metal4 ( -2707 -1113 ) ( -2693 -1099 ) ++ + LAYER metal4 ( -3607 -7 ) ( -3593 7 ) ++ + LAYER metal4 ( -3607 -1113 ) ( -3593 -1099 ) ++ + LAYER metal4 ( -4507 -7 ) ( -4493 7 ) ++ + LAYER metal4 ( -4507 -1113 ) ( -4493 -1099 ) ++ + LAYER metal1 ( 350 3 ) ( 357 11 ) ++ + LAYER metal1 ( -5400 3 ) ( -5393 11 ) ++ + LAYER metal1 ( 350 -277 ) ( 357 -269 ) ++ + LAYER metal1 ( -5400 -277 ) ( -5393 -269 ) ++ + LAYER metal1 ( 350 -557 ) ( 357 -549 ) ++ + LAYER metal1 ( -5400 -557 ) ( -5393 -549 ) ++ + LAYER metal1 ( 350 -837 ) ( 357 -829 ) ++ + LAYER metal1 ( -5400 -837 ) ( -5393 -829 ) ++ + LAYER metal1 ( 350 -1117 ) ( 357 -1109 ) ++ + LAYER metal1 ( -5400 -1117 ) ( -5393 -1109 ) ++ + FIXED ( 5400 1113 ) N ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 314 ) N ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 398 ) N ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 90 ) N ; ++ - addr_w0[0] + NET addr_w0[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 230 ) N ; ++ - addr_w0[1] + NET addr_w0[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 342 ) N ; ++ - addr_w0[2] + NET addr_w0[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 62 ) N ; ++ - addr_w1[0] + NET addr_w1[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 258 ) N ; ++ - addr_w1[1] + NET addr_w1[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 370 ) N ; ++ - addr_w1[2] + NET addr_w1[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal3 ( -3 -3 ) ( 4 4 ) ++ + PLACED ( 5753 286 ) N ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 4881 1113 ) N ; ++ - we0[0] + NET we0[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 4433 1113 ) N ; ++ - we1[0] + NET we1[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER metal4 ( -7 -7 ) ( 7 7 ) ++ + PLACED ( 4545 1113 ) N ; ++END PINS ++SPECIALNETS 2 ; ++ - VDD ( PIN VDD ) ( tapcell.cell8_7 VDD ) ( tapcell.cell8_6 VDD ) ( tapcell.cell8_5 VDD ) ( tapcell.cell8_4 VDD ) ( tapcell.cell8_3 VDD ) ( tapcell.cell8_2 VDD ) ++ ( tapcell.cell8_1 VDD ) ( tapcell.cell8_0 VDD ) ( tapcell.cell7_7 VDD ) ( tapcell.cell7_6 VDD ) ( tapcell.cell7_5 VDD ) ( tapcell.cell7_4 VDD ) ( tapcell.cell7_3 VDD ) ( tapcell.cell7_2 VDD ) ++ ( tapcell.cell7_1 VDD ) ( tapcell.cell7_0 VDD ) ( tapcell.cell6_7 VDD ) ( tapcell.cell6_6 VDD ) ( tapcell.cell6_5 VDD ) ( tapcell.cell6_4 VDD ) ( tapcell.cell6_3 VDD ) ( tapcell.cell6_2 VDD ) ++ ( tapcell.cell6_1 VDD ) ( tapcell.cell6_0 VDD ) ( tapcell.cell5_7 VDD ) ( tapcell.cell5_6 VDD ) ( tapcell.cell5_5 VDD ) ( tapcell.cell5_4 VDD ) ( tapcell.cell5_3 VDD ) ( tapcell.cell5_2 VDD ) ++ ( tapcell.cell5_1 VDD ) ( tapcell.cell5_0 VDD ) ( tapcell.cell4_7 VDD ) ( tapcell.cell4_6 VDD ) ( tapcell.cell4_5 VDD ) ( tapcell.cell4_4 VDD ) ( tapcell.cell4_3 VDD ) ( tapcell.cell4_2 VDD ) ++ ( tapcell.cell4_1 VDD ) ( tapcell.cell4_0 VDD ) ( tapcell.cell3_7 VDD ) ( tapcell.cell3_6 VDD ) ( tapcell.cell3_5 VDD ) ( tapcell.cell3_4 VDD ) ( tapcell.cell3_3 VDD ) ( tapcell.cell3_2 VDD ) ++ ( tapcell.cell3_1 VDD ) ( tapcell.cell3_0 VDD ) ( tapcell.cell2_7 VDD ) ( tapcell.cell2_6 VDD ) ( tapcell.cell2_5 VDD ) ( tapcell.cell2_4 VDD ) ( tapcell.cell2_3 VDD ) ( tapcell.cell2_2 VDD ) ++ ( tapcell.cell2_1 VDD ) ( tapcell.cell2_0 VDD ) ( tapcell.cell1_7 VDD ) ( tapcell.cell1_6 VDD ) ( tapcell.cell1_5 VDD ) ( tapcell.cell1_4 VDD ) ( tapcell.cell1_3 VDD ) ( tapcell.cell1_2 VDD ) ++ ( tapcell.cell1_1 VDD ) ( tapcell.cell1_0 VDD ) ( tapcell.cell0_7 VDD ) ( tapcell.cell0_6 VDD ) ( tapcell.cell0_5 VDD ) ( tapcell.cell0_4 VDD ) ( tapcell.cell0_3 VDD ) ( tapcell.cell0_2 VDD ) ++ ( tapcell.cell0_1 VDD ) ( tapcell.cell0_0 VDD ) ( decoder_p2.inv_p2_a0 VDD ) ( decoder_p2.inv_p2_a1 VDD ) ( decoder_p2.inv_p2_a2 VDD ) ( decoder_p1.inv_p1_a0 VDD ) ( decoder_p0.inv_p0_a0 VDD ) ( decoder_p1.inv_p1_a1 VDD ) ++ ( decoder_p0.inv_p0_a1 VDD ) ( decoder_p1.inv_p1_a2 VDD ) ( decoder_p0.inv_p0_a2 VDD ) ( decoder_p2.and_layer1_word6 VDD ) ( decoder_p2.and_layer0_word6 VDD ) ( decoder_p2.and_layer1_word5 VDD ) ( decoder_p2.and_layer0_word5 VDD ) ( decoder_p2.and_layer1_word4 VDD ) ++ ( decoder_p2.and_layer0_word4 VDD ) ( decoder_p2.and_layer1_word3 VDD ) ( decoder_p2.and_layer0_word3 VDD ) ( decoder_p2.and_layer1_word2 VDD ) ( decoder_p2.and_layer0_word2 VDD ) ( decoder_p2.and_layer1_word1 VDD ) ( decoder_p2.and_layer0_word1 VDD ) ( decoder_p2.and_layer1_word0 VDD ) ++ ( decoder_p2.and_layer0_word0 VDD ) ( sel_buf_r_p2.sel_buf_6 VDD ) ( sel_buf_r_p2.sel_buf_5 VDD ) ( sel_buf_r_p2.sel_buf_4 VDD ) ( sel_buf_r_p2.sel_buf_3 VDD ) ( sel_buf_r_p2.sel_buf_2 VDD ) ( sel_buf_r_p2.sel_buf_1 VDD ) ( sel_buf_r_p2.sel_buf_0 VDD ) ++ ( decoder_p1.and_layer1_word6 VDD ) ( decoder_p1.and_layer0_word6 VDD ) ( decoder_p1.and_layer1_word5 VDD ) ( decoder_p1.and_layer0_word5 VDD ) ( decoder_p1.and_layer1_word4 VDD ) ( decoder_p1.and_layer0_word4 VDD ) ( decoder_p1.and_layer1_word3 VDD ) ( decoder_p1.and_layer0_word3 VDD ) ++ ( decoder_p1.and_layer1_word2 VDD ) ( decoder_p1.and_layer0_word2 VDD ) ( decoder_p1.and_layer1_word1 VDD ) ( decoder_p1.and_layer0_word1 VDD ) ( decoder_p1.and_layer1_word0 VDD ) ( decoder_p1.and_layer0_word0 VDD ) ( sel_buf_w_p1.sel_buf_6 VDD ) ( sel_buf_w_p1.sel_buf_5 VDD ) ++ ( sel_buf_w_p1.sel_buf_4 VDD ) ( sel_buf_w_p1.sel_buf_3 VDD ) ( sel_buf_w_p1.sel_buf_2 VDD ) ( sel_buf_w_p1.sel_buf_1 VDD ) ( sel_buf_w_p1.sel_buf_0 VDD ) ( decoder_p0.and_layer1_word6 VDD ) ( decoder_p0.and_layer0_word6 VDD ) ( decoder_p0.and_layer1_word5 VDD ) ++ ( decoder_p0.and_layer0_word5 VDD ) ( decoder_p0.and_layer1_word4 VDD ) ( decoder_p0.and_layer0_word4 VDD ) ( decoder_p0.and_layer1_word3 VDD ) ( decoder_p0.and_layer0_word3 VDD ) ( decoder_p0.and_layer1_word2 VDD ) ( decoder_p0.and_layer0_word2 VDD ) ( decoder_p0.and_layer1_word1 VDD ) ++ ( decoder_p0.and_layer0_word1 VDD ) ( decoder_p0.and_layer1_word0 VDD ) ( decoder_p0.and_layer0_word0 VDD ) ( sel_buf_w_p0.sel_buf_6 VDD ) ( sel_buf_w_p0.sel_buf_5 VDD ) ( sel_buf_w_p0.sel_buf_4 VDD ) ( sel_buf_w_p0.sel_buf_3 VDD ) ( sel_buf_w_p0.sel_buf_2 VDD ) ++ ( sel_buf_w_p0.sel_buf_1 VDD ) ( sel_buf_w_p0.sel_buf_0 VDD ) ( buffer1.in[6] VDD ) ( buffer0.in[6] VDD ) ( buffer1.in[5] VDD ) ( buffer0.in[5] VDD ) ( buffer1.in[4] VDD ) ( buffer0.in[4] VDD ) ++ ( buffer1.in[3] VDD ) ( buffer0.in[3] VDD ) ( buffer1.in[2] VDD ) ( buffer0.in[2] VDD ) ( buffer1.in[1] VDD ) ( buffer0.in[1] VDD ) ( buffer1.in[0] VDD ) ( buffer0.in[0] VDD ) ++ ( storage_6_0_0.select_inv_0 VDD ) ( storage_6_0_0.cg VDD ) ( storage_6_0_0.bit6.dmux0_inv VDD ) ( storage_6_0_0.bit6.dmux0 VDD ) ( storage_6_0_0.bit6.obuf0 VDD ) ( storage_6_0_0.bit6.bit VDD ) ( storage_6_0_0.bit5.dmux0_inv VDD ) ( storage_6_0_0.bit5.dmux0 VDD ) ++ ( storage_6_0_0.bit5.obuf0 VDD ) ( storage_6_0_0.bit5.bit VDD ) ( storage_6_0_0.bit4.dmux0_inv VDD ) ( storage_6_0_0.bit4.dmux0 VDD ) ( storage_6_0_0.bit4.obuf0 VDD ) ( storage_6_0_0.bit4.bit VDD ) ( storage_6_0_0.bit3.dmux0_inv VDD ) ( storage_6_0_0.bit3.dmux0 VDD ) ++ ( storage_6_0_0.bit3.obuf0 VDD ) ( storage_6_0_0.bit3.bit VDD ) ( storage_6_0_0.bit2.dmux0_inv VDD ) ( storage_6_0_0.bit2.dmux0 VDD ) ( storage_6_0_0.bit2.obuf0 VDD ) ( storage_6_0_0.bit2.bit VDD ) ( storage_6_0_0.bit1.dmux0_inv VDD ) ( storage_6_0_0.bit1.dmux0 VDD ) ++ ( storage_6_0_0.bit1.obuf0 VDD ) ( storage_6_0_0.bit1.bit VDD ) ( storage_6_0_0.bit0.dmux0_inv VDD ) ( storage_6_0_0.bit0.dmux0 VDD ) ( storage_6_0_0.bit0.obuf0 VDD ) ( storage_6_0_0.bit0.bit VDD ) ( storage_6_0_0.any_or0 VDD ) ( storage_6_0_0.take_and0 VDD ) ++ ( storage_6_0_0.later_inv0 VDD ) ( storage_6_0_0.gcand1 VDD ) ( storage_6_0_0.gcand0 VDD ) ( storage_5_0_0.select_inv_0 VDD ) ( storage_5_0_0.cg VDD ) ( storage_5_0_0.bit6.dmux0_inv VDD ) ( storage_5_0_0.bit6.dmux0 VDD ) ( storage_5_0_0.bit6.obuf0 VDD ) ++ ( storage_5_0_0.bit6.bit VDD ) ( storage_5_0_0.bit5.dmux0_inv VDD ) ( storage_5_0_0.bit5.dmux0 VDD ) ( storage_5_0_0.bit5.obuf0 VDD ) ( storage_5_0_0.bit5.bit VDD ) ( storage_5_0_0.bit4.dmux0_inv VDD ) ( storage_5_0_0.bit4.dmux0 VDD ) ( storage_5_0_0.bit4.obuf0 VDD ) ++ ( storage_5_0_0.bit4.bit VDD ) ( storage_5_0_0.bit3.dmux0_inv VDD ) ( storage_5_0_0.bit3.dmux0 VDD ) ( storage_5_0_0.bit3.obuf0 VDD ) ( storage_5_0_0.bit3.bit VDD ) ( storage_5_0_0.bit2.dmux0_inv VDD ) ( storage_5_0_0.bit2.dmux0 VDD ) ( storage_5_0_0.bit2.obuf0 VDD ) ++ ( storage_5_0_0.bit2.bit VDD ) ( storage_5_0_0.bit1.dmux0_inv VDD ) ( storage_5_0_0.bit1.dmux0 VDD ) ( storage_5_0_0.bit1.obuf0 VDD ) ( storage_5_0_0.bit1.bit VDD ) ( storage_5_0_0.bit0.dmux0_inv VDD ) ( storage_5_0_0.bit0.dmux0 VDD ) ( storage_5_0_0.bit0.obuf0 VDD ) ++ ( storage_5_0_0.bit0.bit VDD ) ( storage_5_0_0.any_or0 VDD ) ( storage_5_0_0.take_and0 VDD ) ( storage_5_0_0.later_inv0 VDD ) ( storage_5_0_0.gcand1 VDD ) ( storage_5_0_0.gcand0 VDD ) ( storage_4_0_0.select_inv_0 VDD ) ( storage_4_0_0.cg VDD ) ++ ( storage_4_0_0.bit6.dmux0_inv VDD ) ( storage_4_0_0.bit6.dmux0 VDD ) ( storage_4_0_0.bit6.obuf0 VDD ) ( storage_4_0_0.bit6.bit VDD ) ( storage_4_0_0.bit5.dmux0_inv VDD ) ( storage_4_0_0.bit5.dmux0 VDD ) ( storage_4_0_0.bit5.obuf0 VDD ) ( storage_4_0_0.bit5.bit VDD ) ++ ( storage_4_0_0.bit4.dmux0_inv VDD ) ( storage_4_0_0.bit4.dmux0 VDD ) ( storage_4_0_0.bit4.obuf0 VDD ) ( storage_4_0_0.bit4.bit VDD ) ( storage_4_0_0.bit3.dmux0_inv VDD ) ( storage_4_0_0.bit3.dmux0 VDD ) ( storage_4_0_0.bit3.obuf0 VDD ) ( storage_4_0_0.bit3.bit VDD ) ++ ( storage_4_0_0.bit2.dmux0_inv VDD ) ( storage_4_0_0.bit2.dmux0 VDD ) ( storage_4_0_0.bit2.obuf0 VDD ) ( storage_4_0_0.bit2.bit VDD ) ( storage_4_0_0.bit1.dmux0_inv VDD ) ( storage_4_0_0.bit1.dmux0 VDD ) ( storage_4_0_0.bit1.obuf0 VDD ) ( storage_4_0_0.bit1.bit VDD ) ++ ( storage_4_0_0.bit0.dmux0_inv VDD ) ( storage_4_0_0.bit0.dmux0 VDD ) ( storage_4_0_0.bit0.obuf0 VDD ) ( storage_4_0_0.bit0.bit VDD ) ( storage_4_0_0.any_or0 VDD ) ( storage_4_0_0.take_and0 VDD ) ( storage_4_0_0.later_inv0 VDD ) ( storage_4_0_0.gcand1 VDD ) ++ ( storage_4_0_0.gcand0 VDD ) ( storage_3_0_0.select_inv_0 VDD ) ( storage_3_0_0.cg VDD ) ( storage_3_0_0.bit6.dmux0_inv VDD ) ( storage_3_0_0.bit6.dmux0 VDD ) ( storage_3_0_0.bit6.obuf0 VDD ) ( storage_3_0_0.bit6.bit VDD ) ( storage_3_0_0.bit5.dmux0_inv VDD ) ++ ( storage_3_0_0.bit5.dmux0 VDD ) ( storage_3_0_0.bit5.obuf0 VDD ) ( storage_3_0_0.bit5.bit VDD ) ( storage_3_0_0.bit4.dmux0_inv VDD ) ( storage_3_0_0.bit4.dmux0 VDD ) ( storage_3_0_0.bit4.obuf0 VDD ) ( storage_3_0_0.bit4.bit VDD ) ( storage_3_0_0.bit3.dmux0_inv VDD ) ++ ( storage_3_0_0.bit3.dmux0 VDD ) ( storage_3_0_0.bit3.obuf0 VDD ) ( storage_3_0_0.bit3.bit VDD ) ( storage_3_0_0.bit2.dmux0_inv VDD ) ( storage_3_0_0.bit2.dmux0 VDD ) ( storage_3_0_0.bit2.obuf0 VDD ) ( storage_3_0_0.bit2.bit VDD ) ( storage_3_0_0.bit1.dmux0_inv VDD ) ++ ( storage_3_0_0.bit1.dmux0 VDD ) ( storage_3_0_0.bit1.obuf0 VDD ) ( storage_3_0_0.bit1.bit VDD ) ( storage_3_0_0.bit0.dmux0_inv VDD ) ( storage_3_0_0.bit0.dmux0 VDD ) ( storage_3_0_0.bit0.obuf0 VDD ) ( storage_3_0_0.bit0.bit VDD ) ( storage_3_0_0.any_or0 VDD ) ++ ( storage_3_0_0.take_and0 VDD ) ( storage_3_0_0.later_inv0 VDD ) ( storage_3_0_0.gcand1 VDD ) ( storage_3_0_0.gcand0 VDD ) ( storage_2_0_0.select_inv_0 VDD ) ( storage_2_0_0.cg VDD ) ( storage_2_0_0.bit6.dmux0_inv VDD ) ( storage_2_0_0.bit6.dmux0 VDD ) ++ ( storage_2_0_0.bit6.obuf0 VDD ) ( storage_2_0_0.bit6.bit VDD ) ( storage_2_0_0.bit5.dmux0_inv VDD ) ( storage_2_0_0.bit5.dmux0 VDD ) ( storage_2_0_0.bit5.obuf0 VDD ) ( storage_2_0_0.bit5.bit VDD ) ( storage_2_0_0.bit4.dmux0_inv VDD ) ( storage_2_0_0.bit4.dmux0 VDD ) ++ ( storage_2_0_0.bit4.obuf0 VDD ) ( storage_2_0_0.bit4.bit VDD ) ( storage_2_0_0.bit3.dmux0_inv VDD ) ( storage_2_0_0.bit3.dmux0 VDD ) ( storage_2_0_0.bit3.obuf0 VDD ) ( storage_2_0_0.bit3.bit VDD ) ( storage_2_0_0.bit2.dmux0_inv VDD ) ( storage_2_0_0.bit2.dmux0 VDD ) ++ ( storage_2_0_0.bit2.obuf0 VDD ) ( storage_2_0_0.bit2.bit VDD ) ( storage_2_0_0.bit1.dmux0_inv VDD ) ( storage_2_0_0.bit1.dmux0 VDD ) ( storage_2_0_0.bit1.obuf0 VDD ) ( storage_2_0_0.bit1.bit VDD ) ( storage_2_0_0.bit0.dmux0_inv VDD ) ( storage_2_0_0.bit0.dmux0 VDD ) ++ ( storage_2_0_0.bit0.obuf0 VDD ) ( storage_2_0_0.bit0.bit VDD ) ( storage_2_0_0.any_or0 VDD ) ( storage_2_0_0.take_and0 VDD ) ( storage_2_0_0.later_inv0 VDD ) ( storage_2_0_0.gcand1 VDD ) ( storage_2_0_0.gcand0 VDD ) ( storage_1_0_0.select_inv_0 VDD ) ++ ( storage_1_0_0.cg VDD ) ( storage_1_0_0.bit6.dmux0_inv VDD ) ( storage_1_0_0.bit6.dmux0 VDD ) ( storage_1_0_0.bit6.obuf0 VDD ) ( storage_1_0_0.bit6.bit VDD ) ( storage_1_0_0.bit5.dmux0_inv VDD ) ( storage_1_0_0.bit5.dmux0 VDD ) ( storage_1_0_0.bit5.obuf0 VDD ) ++ ( storage_1_0_0.bit5.bit VDD ) ( storage_1_0_0.bit4.dmux0_inv VDD ) ( storage_1_0_0.bit4.dmux0 VDD ) ( storage_1_0_0.bit4.obuf0 VDD ) ( storage_1_0_0.bit4.bit VDD ) ( storage_1_0_0.bit3.dmux0_inv VDD ) ( storage_1_0_0.bit3.dmux0 VDD ) ( storage_1_0_0.bit3.obuf0 VDD ) ++ ( storage_1_0_0.bit3.bit VDD ) ( storage_1_0_0.bit2.dmux0_inv VDD ) ( storage_1_0_0.bit2.dmux0 VDD ) ( storage_1_0_0.bit2.obuf0 VDD ) ( storage_1_0_0.bit2.bit VDD ) ( storage_1_0_0.bit1.dmux0_inv VDD ) ( storage_1_0_0.bit1.dmux0 VDD ) ( storage_1_0_0.bit1.obuf0 VDD ) ++ ( storage_1_0_0.bit1.bit VDD ) ( storage_1_0_0.bit0.dmux0_inv VDD ) ( storage_1_0_0.bit0.dmux0 VDD ) ( storage_1_0_0.bit0.obuf0 VDD ) ( storage_1_0_0.bit0.bit VDD ) ( storage_1_0_0.any_or0 VDD ) ( storage_1_0_0.take_and0 VDD ) ( storage_1_0_0.later_inv0 VDD ) ++ ( storage_1_0_0.gcand1 VDD ) ( storage_1_0_0.gcand0 VDD ) ( storage_0_0_0.select_inv_0 VDD ) ( storage_0_0_0.cg VDD ) ( storage_0_0_0.bit6.dmux0_inv VDD ) ( storage_0_0_0.bit6.dmux0 VDD ) ( storage_0_0_0.bit6.obuf0 VDD ) ( storage_0_0_0.bit6.bit VDD ) ++ ( storage_0_0_0.bit5.dmux0_inv VDD ) ( storage_0_0_0.bit5.dmux0 VDD ) ( storage_0_0_0.bit5.obuf0 VDD ) ( storage_0_0_0.bit5.bit VDD ) ( storage_0_0_0.bit4.dmux0_inv VDD ) ( storage_0_0_0.bit4.dmux0 VDD ) ( storage_0_0_0.bit4.obuf0 VDD ) ( storage_0_0_0.bit4.bit VDD ) ++ ( storage_0_0_0.bit3.dmux0_inv VDD ) ( storage_0_0_0.bit3.dmux0 VDD ) ( storage_0_0_0.bit3.obuf0 VDD ) ( storage_0_0_0.bit3.bit VDD ) ( storage_0_0_0.bit2.dmux0_inv VDD ) ( storage_0_0_0.bit2.dmux0 VDD ) ( storage_0_0_0.bit2.obuf0 VDD ) ( storage_0_0_0.bit2.bit VDD ) ++ ( storage_0_0_0.bit1.dmux0_inv VDD ) ( storage_0_0_0.bit1.dmux0 VDD ) ( storage_0_0_0.bit1.obuf0 VDD ) ( storage_0_0_0.bit1.bit VDD ) ( storage_0_0_0.bit0.dmux0_inv VDD ) ( storage_0_0_0.bit0.dmux0 VDD ) ( storage_0_0_0.bit0.obuf0 VDD ) ( storage_0_0_0.bit0.bit VDD ) ++ ( storage_0_0_0.any_or0 VDD ) ( storage_0_0_0.take_and0 VDD ) ( storage_0_0_0.later_inv0 VDD ) ( storage_0_0_0.gcand1 VDD ) ( storage_0_0_0.gcand0 VDD ) + USE POWER ++ + ROUTED metal4 14 + SHAPE STRIPE ( 4950 0 ) ( 4950 1120 ) ++ NEW metal4 14 + SHAPE STRIPE ( 4050 0 ) ( 4050 1120 ) ++ NEW metal4 14 + SHAPE STRIPE ( 3150 0 ) ( 3150 1120 ) ++ NEW metal4 14 + SHAPE STRIPE ( 2250 0 ) ( 2250 1120 ) ++ NEW metal4 14 + SHAPE STRIPE ( 1350 0 ) ( 1350 1120 ) ++ NEW metal4 14 + SHAPE STRIPE ( 450 0 ) ( 450 1120 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 980 ) ( 5757 980 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 700 ) ( 5757 700 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 420 ) ( 5757 420 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 140 ) ( 5757 140 ) ++ NEW metal3 0 + SHAPE STRIPE ( 4950 980 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4950 980 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4950 980 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4950 700 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4950 700 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4950 700 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4950 420 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4950 420 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4950 420 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4950 140 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4950 140 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4950 140 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4050 980 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4050 980 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4050 980 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4050 700 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4050 700 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4050 700 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4050 420 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4050 420 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4050 420 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4050 140 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4050 140 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4050 140 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3150 980 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3150 980 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3150 980 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3150 700 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3150 700 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3150 700 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3150 420 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3150 420 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3150 420 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3150 140 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3150 140 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3150 140 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2250 980 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2250 980 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2250 980 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2250 700 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2250 700 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2250 700 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2250 420 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2250 420 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2250 420 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2250 140 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2250 140 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2250 140 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1350 980 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1350 980 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1350 980 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1350 700 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1350 700 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1350 700 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1350 420 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1350 420 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1350 420 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1350 140 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1350 140 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1350 140 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 450 980 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 450 980 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 450 980 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 450 700 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 450 700 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 450 700 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 450 420 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 450 420 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 450 420 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 450 140 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 450 140 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 450 140 ) via1_2_280_160_1_1_300_300 ; ++ - VSS ( PIN VSS ) ( tapcell.cell8_7 VSS ) ( tapcell.cell8_6 VSS ) ( tapcell.cell8_5 VSS ) ( tapcell.cell8_4 VSS ) ( tapcell.cell8_3 VSS ) ( tapcell.cell8_2 VSS ) ++ ( tapcell.cell8_1 VSS ) ( tapcell.cell8_0 VSS ) ( tapcell.cell7_7 VSS ) ( tapcell.cell7_6 VSS ) ( tapcell.cell7_5 VSS ) ( tapcell.cell7_4 VSS ) ( tapcell.cell7_3 VSS ) ( tapcell.cell7_2 VSS ) ++ ( tapcell.cell7_1 VSS ) ( tapcell.cell7_0 VSS ) ( tapcell.cell6_7 VSS ) ( tapcell.cell6_6 VSS ) ( tapcell.cell6_5 VSS ) ( tapcell.cell6_4 VSS ) ( tapcell.cell6_3 VSS ) ( tapcell.cell6_2 VSS ) ++ ( tapcell.cell6_1 VSS ) ( tapcell.cell6_0 VSS ) ( tapcell.cell5_7 VSS ) ( tapcell.cell5_6 VSS ) ( tapcell.cell5_5 VSS ) ( tapcell.cell5_4 VSS ) ( tapcell.cell5_3 VSS ) ( tapcell.cell5_2 VSS ) ++ ( tapcell.cell5_1 VSS ) ( tapcell.cell5_0 VSS ) ( tapcell.cell4_7 VSS ) ( tapcell.cell4_6 VSS ) ( tapcell.cell4_5 VSS ) ( tapcell.cell4_4 VSS ) ( tapcell.cell4_3 VSS ) ( tapcell.cell4_2 VSS ) ++ ( tapcell.cell4_1 VSS ) ( tapcell.cell4_0 VSS ) ( tapcell.cell3_7 VSS ) ( tapcell.cell3_6 VSS ) ( tapcell.cell3_5 VSS ) ( tapcell.cell3_4 VSS ) ( tapcell.cell3_3 VSS ) ( tapcell.cell3_2 VSS ) ++ ( tapcell.cell3_1 VSS ) ( tapcell.cell3_0 VSS ) ( tapcell.cell2_7 VSS ) ( tapcell.cell2_6 VSS ) ( tapcell.cell2_5 VSS ) ( tapcell.cell2_4 VSS ) ( tapcell.cell2_3 VSS ) ( tapcell.cell2_2 VSS ) ++ ( tapcell.cell2_1 VSS ) ( tapcell.cell2_0 VSS ) ( tapcell.cell1_7 VSS ) ( tapcell.cell1_6 VSS ) ( tapcell.cell1_5 VSS ) ( tapcell.cell1_4 VSS ) ( tapcell.cell1_3 VSS ) ( tapcell.cell1_2 VSS ) ++ ( tapcell.cell1_1 VSS ) ( tapcell.cell1_0 VSS ) ( tapcell.cell0_7 VSS ) ( tapcell.cell0_6 VSS ) ( tapcell.cell0_5 VSS ) ( tapcell.cell0_4 VSS ) ( tapcell.cell0_3 VSS ) ( tapcell.cell0_2 VSS ) ++ ( tapcell.cell0_1 VSS ) ( tapcell.cell0_0 VSS ) ( decoder_p2.inv_p2_a0 VSS ) ( decoder_p2.inv_p2_a1 VSS ) ( decoder_p2.inv_p2_a2 VSS ) ( decoder_p1.inv_p1_a0 VSS ) ( decoder_p0.inv_p0_a0 VSS ) ( decoder_p1.inv_p1_a1 VSS ) ++ ( decoder_p0.inv_p0_a1 VSS ) ( decoder_p1.inv_p1_a2 VSS ) ( decoder_p0.inv_p0_a2 VSS ) ( decoder_p2.and_layer1_word6 VSS ) ( decoder_p2.and_layer0_word6 VSS ) ( decoder_p2.and_layer1_word5 VSS ) ( decoder_p2.and_layer0_word5 VSS ) ( decoder_p2.and_layer1_word4 VSS ) ++ ( decoder_p2.and_layer0_word4 VSS ) ( decoder_p2.and_layer1_word3 VSS ) ( decoder_p2.and_layer0_word3 VSS ) ( decoder_p2.and_layer1_word2 VSS ) ( decoder_p2.and_layer0_word2 VSS ) ( decoder_p2.and_layer1_word1 VSS ) ( decoder_p2.and_layer0_word1 VSS ) ( decoder_p2.and_layer1_word0 VSS ) ++ ( decoder_p2.and_layer0_word0 VSS ) ( sel_buf_r_p2.sel_buf_6 VSS ) ( sel_buf_r_p2.sel_buf_5 VSS ) ( sel_buf_r_p2.sel_buf_4 VSS ) ( sel_buf_r_p2.sel_buf_3 VSS ) ( sel_buf_r_p2.sel_buf_2 VSS ) ( sel_buf_r_p2.sel_buf_1 VSS ) ( sel_buf_r_p2.sel_buf_0 VSS ) ++ ( decoder_p1.and_layer1_word6 VSS ) ( decoder_p1.and_layer0_word6 VSS ) ( decoder_p1.and_layer1_word5 VSS ) ( decoder_p1.and_layer0_word5 VSS ) ( decoder_p1.and_layer1_word4 VSS ) ( decoder_p1.and_layer0_word4 VSS ) ( decoder_p1.and_layer1_word3 VSS ) ( decoder_p1.and_layer0_word3 VSS ) ++ ( decoder_p1.and_layer1_word2 VSS ) ( decoder_p1.and_layer0_word2 VSS ) ( decoder_p1.and_layer1_word1 VSS ) ( decoder_p1.and_layer0_word1 VSS ) ( decoder_p1.and_layer1_word0 VSS ) ( decoder_p1.and_layer0_word0 VSS ) ( sel_buf_w_p1.sel_buf_6 VSS ) ( sel_buf_w_p1.sel_buf_5 VSS ) ++ ( sel_buf_w_p1.sel_buf_4 VSS ) ( sel_buf_w_p1.sel_buf_3 VSS ) ( sel_buf_w_p1.sel_buf_2 VSS ) ( sel_buf_w_p1.sel_buf_1 VSS ) ( sel_buf_w_p1.sel_buf_0 VSS ) ( decoder_p0.and_layer1_word6 VSS ) ( decoder_p0.and_layer0_word6 VSS ) ( decoder_p0.and_layer1_word5 VSS ) ++ ( decoder_p0.and_layer0_word5 VSS ) ( decoder_p0.and_layer1_word4 VSS ) ( decoder_p0.and_layer0_word4 VSS ) ( decoder_p0.and_layer1_word3 VSS ) ( decoder_p0.and_layer0_word3 VSS ) ( decoder_p0.and_layer1_word2 VSS ) ( decoder_p0.and_layer0_word2 VSS ) ( decoder_p0.and_layer1_word1 VSS ) ++ ( decoder_p0.and_layer0_word1 VSS ) ( decoder_p0.and_layer1_word0 VSS ) ( decoder_p0.and_layer0_word0 VSS ) ( sel_buf_w_p0.sel_buf_6 VSS ) ( sel_buf_w_p0.sel_buf_5 VSS ) ( sel_buf_w_p0.sel_buf_4 VSS ) ( sel_buf_w_p0.sel_buf_3 VSS ) ( sel_buf_w_p0.sel_buf_2 VSS ) ++ ( sel_buf_w_p0.sel_buf_1 VSS ) ( sel_buf_w_p0.sel_buf_0 VSS ) ( buffer1.in[6] VSS ) ( buffer0.in[6] VSS ) ( buffer1.in[5] VSS ) ( buffer0.in[5] VSS ) ( buffer1.in[4] VSS ) ( buffer0.in[4] VSS ) ++ ( buffer1.in[3] VSS ) ( buffer0.in[3] VSS ) ( buffer1.in[2] VSS ) ( buffer0.in[2] VSS ) ( buffer1.in[1] VSS ) ( buffer0.in[1] VSS ) ( buffer1.in[0] VSS ) ( buffer0.in[0] VSS ) ++ ( storage_6_0_0.select_inv_0 VSS ) ( storage_6_0_0.cg VSS ) ( storage_6_0_0.bit6.dmux0_inv VSS ) ( storage_6_0_0.bit6.dmux0 VSS ) ( storage_6_0_0.bit6.obuf0 VSS ) ( storage_6_0_0.bit6.bit VSS ) ( storage_6_0_0.bit5.dmux0_inv VSS ) ( storage_6_0_0.bit5.dmux0 VSS ) ++ ( storage_6_0_0.bit5.obuf0 VSS ) ( storage_6_0_0.bit5.bit VSS ) ( storage_6_0_0.bit4.dmux0_inv VSS ) ( storage_6_0_0.bit4.dmux0 VSS ) ( storage_6_0_0.bit4.obuf0 VSS ) ( storage_6_0_0.bit4.bit VSS ) ( storage_6_0_0.bit3.dmux0_inv VSS ) ( storage_6_0_0.bit3.dmux0 VSS ) ++ ( storage_6_0_0.bit3.obuf0 VSS ) ( storage_6_0_0.bit3.bit VSS ) ( storage_6_0_0.bit2.dmux0_inv VSS ) ( storage_6_0_0.bit2.dmux0 VSS ) ( storage_6_0_0.bit2.obuf0 VSS ) ( storage_6_0_0.bit2.bit VSS ) ( storage_6_0_0.bit1.dmux0_inv VSS ) ( storage_6_0_0.bit1.dmux0 VSS ) ++ ( storage_6_0_0.bit1.obuf0 VSS ) ( storage_6_0_0.bit1.bit VSS ) ( storage_6_0_0.bit0.dmux0_inv VSS ) ( storage_6_0_0.bit0.dmux0 VSS ) ( storage_6_0_0.bit0.obuf0 VSS ) ( storage_6_0_0.bit0.bit VSS ) ( storage_6_0_0.any_or0 VSS ) ( storage_6_0_0.take_and0 VSS ) ++ ( storage_6_0_0.later_inv0 VSS ) ( storage_6_0_0.gcand1 VSS ) ( storage_6_0_0.gcand0 VSS ) ( storage_5_0_0.select_inv_0 VSS ) ( storage_5_0_0.cg VSS ) ( storage_5_0_0.bit6.dmux0_inv VSS ) ( storage_5_0_0.bit6.dmux0 VSS ) ( storage_5_0_0.bit6.obuf0 VSS ) ++ ( storage_5_0_0.bit6.bit VSS ) ( storage_5_0_0.bit5.dmux0_inv VSS ) ( storage_5_0_0.bit5.dmux0 VSS ) ( storage_5_0_0.bit5.obuf0 VSS ) ( storage_5_0_0.bit5.bit VSS ) ( storage_5_0_0.bit4.dmux0_inv VSS ) ( storage_5_0_0.bit4.dmux0 VSS ) ( storage_5_0_0.bit4.obuf0 VSS ) ++ ( storage_5_0_0.bit4.bit VSS ) ( storage_5_0_0.bit3.dmux0_inv VSS ) ( storage_5_0_0.bit3.dmux0 VSS ) ( storage_5_0_0.bit3.obuf0 VSS ) ( storage_5_0_0.bit3.bit VSS ) ( storage_5_0_0.bit2.dmux0_inv VSS ) ( storage_5_0_0.bit2.dmux0 VSS ) ( storage_5_0_0.bit2.obuf0 VSS ) ++ ( storage_5_0_0.bit2.bit VSS ) ( storage_5_0_0.bit1.dmux0_inv VSS ) ( storage_5_0_0.bit1.dmux0 VSS ) ( storage_5_0_0.bit1.obuf0 VSS ) ( storage_5_0_0.bit1.bit VSS ) ( storage_5_0_0.bit0.dmux0_inv VSS ) ( storage_5_0_0.bit0.dmux0 VSS ) ( storage_5_0_0.bit0.obuf0 VSS ) ++ ( storage_5_0_0.bit0.bit VSS ) ( storage_5_0_0.any_or0 VSS ) ( storage_5_0_0.take_and0 VSS ) ( storage_5_0_0.later_inv0 VSS ) ( storage_5_0_0.gcand1 VSS ) ( storage_5_0_0.gcand0 VSS ) ( storage_4_0_0.select_inv_0 VSS ) ( storage_4_0_0.cg VSS ) ++ ( storage_4_0_0.bit6.dmux0_inv VSS ) ( storage_4_0_0.bit6.dmux0 VSS ) ( storage_4_0_0.bit6.obuf0 VSS ) ( storage_4_0_0.bit6.bit VSS ) ( storage_4_0_0.bit5.dmux0_inv VSS ) ( storage_4_0_0.bit5.dmux0 VSS ) ( storage_4_0_0.bit5.obuf0 VSS ) ( storage_4_0_0.bit5.bit VSS ) ++ ( storage_4_0_0.bit4.dmux0_inv VSS ) ( storage_4_0_0.bit4.dmux0 VSS ) ( storage_4_0_0.bit4.obuf0 VSS ) ( storage_4_0_0.bit4.bit VSS ) ( storage_4_0_0.bit3.dmux0_inv VSS ) ( storage_4_0_0.bit3.dmux0 VSS ) ( storage_4_0_0.bit3.obuf0 VSS ) ( storage_4_0_0.bit3.bit VSS ) ++ ( storage_4_0_0.bit2.dmux0_inv VSS ) ( storage_4_0_0.bit2.dmux0 VSS ) ( storage_4_0_0.bit2.obuf0 VSS ) ( storage_4_0_0.bit2.bit VSS ) ( storage_4_0_0.bit1.dmux0_inv VSS ) ( storage_4_0_0.bit1.dmux0 VSS ) ( storage_4_0_0.bit1.obuf0 VSS ) ( storage_4_0_0.bit1.bit VSS ) ++ ( storage_4_0_0.bit0.dmux0_inv VSS ) ( storage_4_0_0.bit0.dmux0 VSS ) ( storage_4_0_0.bit0.obuf0 VSS ) ( storage_4_0_0.bit0.bit VSS ) ( storage_4_0_0.any_or0 VSS ) ( storage_4_0_0.take_and0 VSS ) ( storage_4_0_0.later_inv0 VSS ) ( storage_4_0_0.gcand1 VSS ) ++ ( storage_4_0_0.gcand0 VSS ) ( storage_3_0_0.select_inv_0 VSS ) ( storage_3_0_0.cg VSS ) ( storage_3_0_0.bit6.dmux0_inv VSS ) ( storage_3_0_0.bit6.dmux0 VSS ) ( storage_3_0_0.bit6.obuf0 VSS ) ( storage_3_0_0.bit6.bit VSS ) ( storage_3_0_0.bit5.dmux0_inv VSS ) ++ ( storage_3_0_0.bit5.dmux0 VSS ) ( storage_3_0_0.bit5.obuf0 VSS ) ( storage_3_0_0.bit5.bit VSS ) ( storage_3_0_0.bit4.dmux0_inv VSS ) ( storage_3_0_0.bit4.dmux0 VSS ) ( storage_3_0_0.bit4.obuf0 VSS ) ( storage_3_0_0.bit4.bit VSS ) ( storage_3_0_0.bit3.dmux0_inv VSS ) ++ ( storage_3_0_0.bit3.dmux0 VSS ) ( storage_3_0_0.bit3.obuf0 VSS ) ( storage_3_0_0.bit3.bit VSS ) ( storage_3_0_0.bit2.dmux0_inv VSS ) ( storage_3_0_0.bit2.dmux0 VSS ) ( storage_3_0_0.bit2.obuf0 VSS ) ( storage_3_0_0.bit2.bit VSS ) ( storage_3_0_0.bit1.dmux0_inv VSS ) ++ ( storage_3_0_0.bit1.dmux0 VSS ) ( storage_3_0_0.bit1.obuf0 VSS ) ( storage_3_0_0.bit1.bit VSS ) ( storage_3_0_0.bit0.dmux0_inv VSS ) ( storage_3_0_0.bit0.dmux0 VSS ) ( storage_3_0_0.bit0.obuf0 VSS ) ( storage_3_0_0.bit0.bit VSS ) ( storage_3_0_0.any_or0 VSS ) ++ ( storage_3_0_0.take_and0 VSS ) ( storage_3_0_0.later_inv0 VSS ) ( storage_3_0_0.gcand1 VSS ) ( storage_3_0_0.gcand0 VSS ) ( storage_2_0_0.select_inv_0 VSS ) ( storage_2_0_0.cg VSS ) ( storage_2_0_0.bit6.dmux0_inv VSS ) ( storage_2_0_0.bit6.dmux0 VSS ) ++ ( storage_2_0_0.bit6.obuf0 VSS ) ( storage_2_0_0.bit6.bit VSS ) ( storage_2_0_0.bit5.dmux0_inv VSS ) ( storage_2_0_0.bit5.dmux0 VSS ) ( storage_2_0_0.bit5.obuf0 VSS ) ( storage_2_0_0.bit5.bit VSS ) ( storage_2_0_0.bit4.dmux0_inv VSS ) ( storage_2_0_0.bit4.dmux0 VSS ) ++ ( storage_2_0_0.bit4.obuf0 VSS ) ( storage_2_0_0.bit4.bit VSS ) ( storage_2_0_0.bit3.dmux0_inv VSS ) ( storage_2_0_0.bit3.dmux0 VSS ) ( storage_2_0_0.bit3.obuf0 VSS ) ( storage_2_0_0.bit3.bit VSS ) ( storage_2_0_0.bit2.dmux0_inv VSS ) ( storage_2_0_0.bit2.dmux0 VSS ) ++ ( storage_2_0_0.bit2.obuf0 VSS ) ( storage_2_0_0.bit2.bit VSS ) ( storage_2_0_0.bit1.dmux0_inv VSS ) ( storage_2_0_0.bit1.dmux0 VSS ) ( storage_2_0_0.bit1.obuf0 VSS ) ( storage_2_0_0.bit1.bit VSS ) ( storage_2_0_0.bit0.dmux0_inv VSS ) ( storage_2_0_0.bit0.dmux0 VSS ) ++ ( storage_2_0_0.bit0.obuf0 VSS ) ( storage_2_0_0.bit0.bit VSS ) ( storage_2_0_0.any_or0 VSS ) ( storage_2_0_0.take_and0 VSS ) ( storage_2_0_0.later_inv0 VSS ) ( storage_2_0_0.gcand1 VSS ) ( storage_2_0_0.gcand0 VSS ) ( storage_1_0_0.select_inv_0 VSS ) ++ ( storage_1_0_0.cg VSS ) ( storage_1_0_0.bit6.dmux0_inv VSS ) ( storage_1_0_0.bit6.dmux0 VSS ) ( storage_1_0_0.bit6.obuf0 VSS ) ( storage_1_0_0.bit6.bit VSS ) ( storage_1_0_0.bit5.dmux0_inv VSS ) ( storage_1_0_0.bit5.dmux0 VSS ) ( storage_1_0_0.bit5.obuf0 VSS ) ++ ( storage_1_0_0.bit5.bit VSS ) ( storage_1_0_0.bit4.dmux0_inv VSS ) ( storage_1_0_0.bit4.dmux0 VSS ) ( storage_1_0_0.bit4.obuf0 VSS ) ( storage_1_0_0.bit4.bit VSS ) ( storage_1_0_0.bit3.dmux0_inv VSS ) ( storage_1_0_0.bit3.dmux0 VSS ) ( storage_1_0_0.bit3.obuf0 VSS ) ++ ( storage_1_0_0.bit3.bit VSS ) ( storage_1_0_0.bit2.dmux0_inv VSS ) ( storage_1_0_0.bit2.dmux0 VSS ) ( storage_1_0_0.bit2.obuf0 VSS ) ( storage_1_0_0.bit2.bit VSS ) ( storage_1_0_0.bit1.dmux0_inv VSS ) ( storage_1_0_0.bit1.dmux0 VSS ) ( storage_1_0_0.bit1.obuf0 VSS ) ++ ( storage_1_0_0.bit1.bit VSS ) ( storage_1_0_0.bit0.dmux0_inv VSS ) ( storage_1_0_0.bit0.dmux0 VSS ) ( storage_1_0_0.bit0.obuf0 VSS ) ( storage_1_0_0.bit0.bit VSS ) ( storage_1_0_0.any_or0 VSS ) ( storage_1_0_0.take_and0 VSS ) ( storage_1_0_0.later_inv0 VSS ) ++ ( storage_1_0_0.gcand1 VSS ) ( storage_1_0_0.gcand0 VSS ) ( storage_0_0_0.select_inv_0 VSS ) ( storage_0_0_0.cg VSS ) ( storage_0_0_0.bit6.dmux0_inv VSS ) ( storage_0_0_0.bit6.dmux0 VSS ) ( storage_0_0_0.bit6.obuf0 VSS ) ( storage_0_0_0.bit6.bit VSS ) ++ ( storage_0_0_0.bit5.dmux0_inv VSS ) ( storage_0_0_0.bit5.dmux0 VSS ) ( storage_0_0_0.bit5.obuf0 VSS ) ( storage_0_0_0.bit5.bit VSS ) ( storage_0_0_0.bit4.dmux0_inv VSS ) ( storage_0_0_0.bit4.dmux0 VSS ) ( storage_0_0_0.bit4.obuf0 VSS ) ( storage_0_0_0.bit4.bit VSS ) ++ ( storage_0_0_0.bit3.dmux0_inv VSS ) ( storage_0_0_0.bit3.dmux0 VSS ) ( storage_0_0_0.bit3.obuf0 VSS ) ( storage_0_0_0.bit3.bit VSS ) ( storage_0_0_0.bit2.dmux0_inv VSS ) ( storage_0_0_0.bit2.dmux0 VSS ) ( storage_0_0_0.bit2.obuf0 VSS ) ( storage_0_0_0.bit2.bit VSS ) ++ ( storage_0_0_0.bit1.dmux0_inv VSS ) ( storage_0_0_0.bit1.dmux0 VSS ) ( storage_0_0_0.bit1.obuf0 VSS ) ( storage_0_0_0.bit1.bit VSS ) ( storage_0_0_0.bit0.dmux0_inv VSS ) ( storage_0_0_0.bit0.dmux0 VSS ) ( storage_0_0_0.bit0.obuf0 VSS ) ( storage_0_0_0.bit0.bit VSS ) ++ ( storage_0_0_0.any_or0 VSS ) ( storage_0_0_0.take_and0 VSS ) ( storage_0_0_0.later_inv0 VSS ) ( storage_0_0_0.gcand1 VSS ) ( storage_0_0_0.gcand0 VSS ) + USE GROUND ++ + ROUTED metal4 14 + SHAPE STRIPE ( 5400 -7 ) ( 5400 1127 ) ++ NEW metal4 14 + SHAPE STRIPE ( 4500 -7 ) ( 4500 1127 ) ++ NEW metal4 14 + SHAPE STRIPE ( 3600 -7 ) ( 3600 1127 ) ++ NEW metal4 14 + SHAPE STRIPE ( 2700 -7 ) ( 2700 1127 ) ++ NEW metal4 14 + SHAPE STRIPE ( 1800 -7 ) ( 1800 1127 ) ++ NEW metal4 14 + SHAPE STRIPE ( 900 -7 ) ( 900 1127 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 1120 ) ( 5757 1120 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 840 ) ( 5757 840 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 560 ) ( 5757 560 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 280 ) ( 5757 280 ) ++ NEW metal1 8 + SHAPE FOLLOWPIN ( 0 0 ) ( 5757 0 ) ++ NEW metal3 0 + SHAPE STRIPE ( 5400 1120 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 5400 1120 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 5400 1120 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 5400 840 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 5400 840 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 5400 840 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 5400 560 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 5400 560 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 5400 560 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 5400 280 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 5400 280 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 5400 280 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 5400 0 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 5400 0 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 5400 0 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4500 1120 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4500 1120 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4500 1120 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4500 840 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4500 840 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4500 840 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4500 560 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4500 560 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4500 560 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4500 280 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4500 280 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4500 280 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 4500 0 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 4500 0 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 4500 0 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3600 1120 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3600 1120 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3600 1120 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3600 840 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3600 840 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3600 840 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3600 560 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3600 560 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3600 560 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3600 280 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3600 280 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3600 280 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 3600 0 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 3600 0 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 3600 0 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2700 1120 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2700 1120 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2700 1120 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2700 840 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2700 840 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2700 840 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2700 560 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2700 560 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2700 560 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2700 280 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2700 280 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2700 280 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 2700 0 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 2700 0 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 2700 0 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1800 1120 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1800 1120 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1800 1120 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1800 840 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1800 840 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1800 840 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1800 560 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1800 560 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1800 560 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1800 280 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1800 280 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1800 280 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 1800 0 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 1800 0 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 1800 0 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 900 1120 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 900 1120 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 900 1120 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 900 840 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 900 840 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 900 840 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 900 560 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 900 560 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 900 560 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 900 280 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 900 280 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 900 280 ) via1_2_280_160_1_1_300_300 ++ NEW metal3 0 + SHAPE STRIPE ( 900 0 ) via3_4_280_160_1_1_320_320 ++ NEW metal2 0 + SHAPE STRIPE ( 900 0 ) via2_3_280_160_1_1_320_320 ++ NEW metal1 0 + SHAPE STRIPE ( 900 0 ) via1_2_280_160_1_1_300_300 ; ++END SPECIALNETS ++NETS 315 ; ++ - D0[0] ( PIN D0[0] ) ( buffer0.in[0] A ) + USE SIGNAL ++ + ROUTED metal4 ( 9 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 9 1057 ) ( 28 * ) ++ NEW metal3 ( 9 1057 ) via3_2 ++ NEW metal1 ( 28 1057 ) via1_4 ++ NEW metal2 ( 28 1057 ) via2_5 ; ++ - D0[1] ( PIN D0[1] ) ( buffer0.in[1] A ) + USE SIGNAL ++ + ROUTED metal4 ( 681 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 655 1057 ) ( 681 * ) ++ NEW metal3 ( 681 1057 ) via3_2 ++ NEW metal1 ( 655 1057 ) via1_4 ++ NEW metal2 ( 655 1057 ) via2_5 ; ++ - D0[2] ( PIN D0[2] ) ( buffer0.in[2] A ) + USE SIGNAL ++ + ROUTED metal4 ( 1297 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 1282 1057 ) ( 1297 * ) ++ NEW metal3 ( 1297 1057 ) via3_2 ++ NEW metal1 ( 1282 1057 ) via1_4 ++ NEW metal2 ( 1282 1057 ) via2_5 ; ++ - D0[3] ( PIN D0[3] ) ( buffer0.in[3] A ) + USE SIGNAL ++ + ROUTED metal4 ( 1913 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 1909 1057 ) ( 1913 * ) ++ NEW metal3 ( 1913 1057 ) via3_2 ++ NEW metal1 ( 1909 1057 ) via1_4 ++ NEW metal2 ( 1909 1057 ) via2_5 ; ++ - D0[4] ( PIN D0[4] ) ( buffer0.in[4] A ) + USE SIGNAL ++ + ROUTED metal4 ( 2529 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 2529 1057 ) ( 2536 * ) ++ NEW metal3 ( 2529 1057 ) via3_2 ++ NEW metal1 ( 2536 1057 ) via1_4 ++ NEW metal2 ( 2536 1057 ) via2_5 ; ++ - D0[5] ( PIN D0[5] ) ( buffer0.in[5] A ) + USE SIGNAL ++ + ROUTED metal4 ( 3201 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 3163 1057 ) ( 3201 * ) ++ NEW metal3 ( 3201 1057 ) via3_2 ++ NEW metal1 ( 3163 1057 ) via1_4 ++ NEW metal2 ( 3163 1057 ) via2_5 ; ++ - D0[6] ( PIN D0[6] ) ( buffer0.in[6] A ) + USE SIGNAL ++ + ROUTED metal4 ( 3817 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 3790 1057 ) ( 3817 * ) ++ NEW metal3 ( 3817 1057 ) via3_2 ++ NEW metal1 ( 3790 1057 ) via1_4 ++ NEW metal2 ( 3790 1057 ) via2_5 ; ++ - D0_nets.b0 ( buffer0.in[0] Z ) ( storage_6_0_0.bit0.dmux0 A2 ) ( storage_5_0_0.bit0.dmux0 A2 ) ( storage_4_0_0.bit0.dmux0 A2 ) ( storage_3_0_0.bit0.dmux0 A2 ) ( storage_2_0_0.bit0.dmux0 A2 ) ( storage_1_0_0.bit0.dmux0 A2 ) ++ ( storage_0_0_0.bit0.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 579 903 ) ( * 1001 ) ++ NEW metal3 ( 66 1001 ) ( 579 * ) ++ NEW metal2 ( 579 791 ) ( * 903 ) ++ NEW metal2 ( 579 623 ) ( * 791 ) ++ NEW metal2 ( 579 511 ) ( * 623 ) ++ NEW metal2 ( 579 343 ) ( * 511 ) ++ NEW metal2 ( 579 231 ) ( * 343 ) ++ NEW metal2 ( 579 63 ) ( * 231 ) ++ NEW metal1 ( 579 903 ) via1_4 ++ NEW metal2 ( 579 1001 ) via2_5 ++ NEW metal1 ( 66 1001 ) via1_7 ++ NEW metal2 ( 66 1001 ) via2_5 ++ NEW metal1 ( 579 791 ) via1_4 ++ NEW metal1 ( 579 623 ) via1_4 ++ NEW metal1 ( 579 511 ) via1_4 ++ NEW metal1 ( 579 343 ) via1_4 ++ NEW metal1 ( 579 231 ) via1_4 ++ NEW metal1 ( 579 63 ) via1_4 ; ++ - D0_nets.b1 ( buffer0.in[1] Z ) ( storage_6_0_0.bit1.dmux0 A2 ) ( storage_5_0_0.bit1.dmux0 A2 ) ( storage_4_0_0.bit1.dmux0 A2 ) ( storage_3_0_0.bit1.dmux0 A2 ) ( storage_2_0_0.bit1.dmux0 A2 ) ( storage_1_0_0.bit1.dmux0 A2 ) ++ ( storage_0_0_0.bit1.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 1206 903 ) ( * 1001 ) ++ NEW metal3 ( 693 1001 ) ( 1206 * ) ++ NEW metal2 ( 1206 791 ) ( * 903 ) ++ NEW metal2 ( 1206 623 ) ( * 791 ) ++ NEW metal2 ( 1206 511 ) ( * 623 ) ++ NEW metal2 ( 1206 343 ) ( * 511 ) ++ NEW metal2 ( 1206 231 ) ( * 343 ) ++ NEW metal2 ( 1206 63 ) ( * 231 ) ++ NEW metal1 ( 1206 903 ) via1_4 ++ NEW metal2 ( 1206 1001 ) via2_5 ++ NEW metal1 ( 693 1001 ) via1_7 ++ NEW metal2 ( 693 1001 ) via2_5 ++ NEW metal1 ( 1206 791 ) via1_4 ++ NEW metal1 ( 1206 623 ) via1_4 ++ NEW metal1 ( 1206 511 ) via1_4 ++ NEW metal1 ( 1206 343 ) via1_4 ++ NEW metal1 ( 1206 231 ) via1_4 ++ NEW metal1 ( 1206 63 ) via1_4 ; ++ - D0_nets.b2 ( buffer0.in[2] Z ) ( storage_6_0_0.bit2.dmux0 A2 ) ( storage_5_0_0.bit2.dmux0 A2 ) ( storage_4_0_0.bit2.dmux0 A2 ) ( storage_3_0_0.bit2.dmux0 A2 ) ( storage_2_0_0.bit2.dmux0 A2 ) ( storage_1_0_0.bit2.dmux0 A2 ) ++ ( storage_0_0_0.bit2.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 1833 903 ) ( * 1001 ) ++ NEW metal2 ( 1833 791 ) ( * 903 ) ++ NEW metal2 ( 1833 623 ) ( * 791 ) ++ NEW metal2 ( 1833 511 ) ( * 623 ) ++ NEW metal2 ( 1833 343 ) ( * 511 ) ++ NEW metal2 ( 1833 231 ) ( * 343 ) ++ NEW metal2 ( 1833 63 ) ( * 231 ) ++ NEW metal3 ( 1320 1001 ) ( 1833 * ) ++ NEW metal1 ( 1320 1001 ) via1_7 ++ NEW metal2 ( 1320 1001 ) via2_5 ++ NEW metal1 ( 1833 903 ) via1_4 ++ NEW metal2 ( 1833 1001 ) via2_5 ++ NEW metal1 ( 1833 791 ) via1_4 ++ NEW metal1 ( 1833 623 ) via1_4 ++ NEW metal1 ( 1833 511 ) via1_4 ++ NEW metal1 ( 1833 343 ) via1_4 ++ NEW metal1 ( 1833 231 ) via1_4 ++ NEW metal1 ( 1833 63 ) via1_4 ; ++ - D0_nets.b3 ( buffer0.in[3] Z ) ( storage_6_0_0.bit3.dmux0 A2 ) ( storage_5_0_0.bit3.dmux0 A2 ) ( storage_4_0_0.bit3.dmux0 A2 ) ( storage_3_0_0.bit3.dmux0 A2 ) ( storage_2_0_0.bit3.dmux0 A2 ) ( storage_1_0_0.bit3.dmux0 A2 ) ++ ( storage_0_0_0.bit3.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 2460 903 ) ( * 1001 ) ++ NEW metal3 ( 1947 1001 ) ( 2460 * ) ++ NEW metal2 ( 2460 791 ) ( * 903 ) ++ NEW metal2 ( 2460 623 ) ( * 791 ) ++ NEW metal2 ( 2460 511 ) ( * 623 ) ++ NEW metal2 ( 2460 343 ) ( * 511 ) ++ NEW metal2 ( 2460 231 ) ( * 343 ) ++ NEW metal2 ( 2460 63 ) ( * 231 ) ++ NEW metal1 ( 2460 903 ) via1_4 ++ NEW metal2 ( 2460 1001 ) via2_5 ++ NEW metal1 ( 1947 1001 ) via1_7 ++ NEW metal2 ( 1947 1001 ) via2_5 ++ NEW metal1 ( 2460 791 ) via1_4 ++ NEW metal1 ( 2460 623 ) via1_4 ++ NEW metal1 ( 2460 511 ) via1_4 ++ NEW metal1 ( 2460 343 ) via1_4 ++ NEW metal1 ( 2460 231 ) via1_4 ++ NEW metal1 ( 2460 63 ) via1_4 ; ++ - D0_nets.b4 ( buffer0.in[4] Z ) ( storage_6_0_0.bit4.dmux0 A2 ) ( storage_5_0_0.bit4.dmux0 A2 ) ( storage_4_0_0.bit4.dmux0 A2 ) ( storage_3_0_0.bit4.dmux0 A2 ) ( storage_2_0_0.bit4.dmux0 A2 ) ( storage_1_0_0.bit4.dmux0 A2 ) ++ ( storage_0_0_0.bit4.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 3087 903 ) ( * 1001 ) ++ NEW metal3 ( 2574 1001 ) ( 3087 * ) ++ NEW metal2 ( 3087 791 ) ( * 903 ) ++ NEW metal2 ( 3087 623 ) ( * 791 ) ++ NEW metal2 ( 3087 511 ) ( * 623 ) ++ NEW metal2 ( 3087 343 ) ( * 511 ) ++ NEW metal2 ( 3087 231 ) ( * 343 ) ++ NEW metal2 ( 3087 63 ) ( * 231 ) ++ NEW metal1 ( 3087 903 ) via1_4 ++ NEW metal2 ( 3087 1001 ) via2_5 ++ NEW metal1 ( 2574 1001 ) via1_7 ++ NEW metal2 ( 2574 1001 ) via2_5 ++ NEW metal1 ( 3087 791 ) via1_4 ++ NEW metal1 ( 3087 623 ) via1_4 ++ NEW metal1 ( 3087 511 ) via1_4 ++ NEW metal1 ( 3087 343 ) via1_4 ++ NEW metal1 ( 3087 231 ) via1_4 ++ NEW metal1 ( 3087 63 ) via1_4 ; ++ - D0_nets.b5 ( buffer0.in[5] Z ) ( storage_6_0_0.bit5.dmux0 A2 ) ( storage_5_0_0.bit5.dmux0 A2 ) ( storage_4_0_0.bit5.dmux0 A2 ) ( storage_3_0_0.bit5.dmux0 A2 ) ( storage_2_0_0.bit5.dmux0 A2 ) ( storage_1_0_0.bit5.dmux0 A2 ) ++ ( storage_0_0_0.bit5.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 3714 903 ) ( * 1001 ) ++ NEW metal2 ( 3714 791 ) ( * 903 ) ++ NEW metal2 ( 3714 623 ) ( * 791 ) ++ NEW metal2 ( 3714 511 ) ( * 623 ) ++ NEW metal2 ( 3714 343 ) ( * 511 ) ++ NEW metal2 ( 3714 231 ) ( * 343 ) ++ NEW metal2 ( 3714 63 ) ( * 231 ) ++ NEW metal3 ( 3201 1001 ) ( 3714 * ) ++ NEW metal1 ( 3714 903 ) via1_4 ++ NEW metal2 ( 3714 1001 ) via2_5 ++ NEW metal1 ( 3714 791 ) via1_4 ++ NEW metal1 ( 3714 623 ) via1_4 ++ NEW metal1 ( 3714 511 ) via1_4 ++ NEW metal1 ( 3714 343 ) via1_4 ++ NEW metal1 ( 3714 231 ) via1_4 ++ NEW metal1 ( 3714 63 ) via1_4 ++ NEW metal1 ( 3201 1001 ) via1_7 ++ NEW metal2 ( 3201 1001 ) via2_5 ; ++ - D0_nets.b6 ( buffer0.in[6] Z ) ( storage_6_0_0.bit6.dmux0 A2 ) ( storage_5_0_0.bit6.dmux0 A2 ) ( storage_4_0_0.bit6.dmux0 A2 ) ( storage_3_0_0.bit6.dmux0 A2 ) ( storage_2_0_0.bit6.dmux0 A2 ) ( storage_1_0_0.bit6.dmux0 A2 ) ++ ( storage_0_0_0.bit6.dmux0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 4341 903 ) ( * 1001 ) ++ NEW metal3 ( 3828 1001 ) ( 4341 * ) ++ NEW metal2 ( 4341 791 ) ( * 903 ) ++ NEW metal2 ( 4341 623 ) ( * 791 ) ++ NEW metal2 ( 4341 511 ) ( * 623 ) ++ NEW metal2 ( 4341 343 ) ( * 511 ) ++ NEW metal2 ( 4341 231 ) ( * 343 ) ++ NEW metal2 ( 4341 63 ) ( * 231 ) ++ NEW metal1 ( 4341 903 ) via1_4 ++ NEW metal2 ( 4341 1001 ) via2_5 ++ NEW metal1 ( 3828 1001 ) via1_7 ++ NEW metal2 ( 3828 1001 ) via2_5 ++ NEW metal1 ( 4341 791 ) via1_4 ++ NEW metal1 ( 4341 623 ) via1_4 ++ NEW metal1 ( 4341 511 ) via1_4 ++ NEW metal1 ( 4341 343 ) via1_4 ++ NEW metal1 ( 4341 231 ) via1_4 ++ NEW metal1 ( 4341 63 ) via1_4 ; ++ - D1[0] ( PIN D1[0] ) ( buffer1.in[0] A ) + USE SIGNAL ++ + ROUTED metal4 ( 65 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 65 1057 ) ( 85 * ) ++ NEW metal3 ( 65 1057 ) via3_2 ++ NEW metal1 ( 85 1057 ) via1_4 ++ NEW metal2 ( 85 1057 ) via2_5 ; ++ - D1[1] ( PIN D1[1] ) ( buffer1.in[1] A ) + USE SIGNAL ++ + ROUTED metal4 ( 737 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 712 1057 ) ( 737 * ) ++ NEW metal3 ( 737 1057 ) via3_2 ++ NEW metal1 ( 712 1057 ) via1_4 ++ NEW metal2 ( 712 1057 ) via2_5 ; ++ - D1[2] ( PIN D1[2] ) ( buffer1.in[2] A ) + USE SIGNAL ++ + ROUTED metal4 ( 1409 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 1339 1057 ) ( 1409 * ) ++ NEW metal3 ( 1409 1057 ) via3_2 ++ NEW metal1 ( 1339 1057 ) via1_4 ++ NEW metal2 ( 1339 1057 ) via2_5 ; ++ - D1[3] ( PIN D1[3] ) ( buffer1.in[3] A ) + USE SIGNAL ++ + ROUTED metal4 ( 1969 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 1966 1057 ) ( 1969 * ) ++ NEW metal3 ( 1969 1057 ) via3_2 ++ NEW metal1 ( 1966 1057 ) via1_4 ++ NEW metal2 ( 1966 1057 ) via2_5 ; ++ - D1[4] ( PIN D1[4] ) ( buffer1.in[4] A ) + USE SIGNAL ++ + ROUTED metal4 ( 2585 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 2585 1057 ) ( 2593 * ) ++ NEW metal3 ( 2585 1057 ) via3_2 ++ NEW metal1 ( 2593 1057 ) via1_4 ++ NEW metal2 ( 2593 1057 ) via2_5 ; ++ - D1[5] ( PIN D1[5] ) ( buffer1.in[5] A ) + USE SIGNAL ++ + ROUTED metal4 ( 3257 1099 ) ( * 1113 0 ) ++ NEW metal3 ( 3220 1099 ) ( 3257 * ) ++ NEW metal2 ( 3220 1057 ) ( * 1099 ) ++ NEW metal3 ( 3257 1099 ) via3_2 ++ NEW metal2 ( 3220 1099 ) via2_5 ++ NEW metal1 ( 3220 1057 ) via1_4 ; ++ - D1[6] ( PIN D1[6] ) ( buffer1.in[6] A ) + USE SIGNAL ++ + ROUTED metal4 ( 3873 1057 ) ( * 1113 0 ) ++ NEW metal3 ( 3847 1057 ) ( 3873 * ) ++ NEW metal3 ( 3873 1057 ) via3_2 ++ NEW metal1 ( 3847 1057 ) via1_4 ++ NEW metal2 ( 3847 1057 ) via2_5 ; ++ - D1_nets.b0 ( buffer1.in[0] Z ) ( storage_6_0_0.bit0.dmux0 B2 ) ( storage_5_0_0.bit0.dmux0 B2 ) ( storage_4_0_0.bit0.dmux0 B2 ) ( storage_3_0_0.bit0.dmux0 B2 ) ( storage_2_0_0.bit0.dmux0 B2 ) ( storage_1_0_0.bit0.dmux0 B2 ) ++ ( storage_0_0_0.bit0.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal3 ( 123 903 ) ( 503 * ) ++ NEW metal2 ( 123 903 ) ( * 1001 ) ++ NEW metal2 ( 503 777 ) ( * 903 ) ++ NEW metal2 ( 503 623 ) ( * 777 ) ++ NEW metal2 ( 503 497 ) ( * 623 ) ++ NEW metal2 ( 503 343 ) ( * 497 ) ++ NEW metal2 ( 503 217 ) ( * 343 ) ++ NEW metal2 ( 503 63 ) ( * 217 ) ++ NEW metal1 ( 503 903 ) via1_4 ++ NEW metal2 ( 503 903 ) via2_5 ++ NEW metal2 ( 123 903 ) via2_5 ++ NEW metal1 ( 123 1001 ) via1_7 ++ NEW metal1 ( 503 777 ) via1_4 ++ NEW metal1 ( 503 623 ) via1_4 ++ NEW metal1 ( 503 497 ) via1_4 ++ NEW metal1 ( 503 343 ) via1_4 ++ NEW metal1 ( 503 217 ) via1_4 ++ NEW metal1 ( 503 63 ) via1_4 ; ++ - D1_nets.b1 ( buffer1.in[1] Z ) ( storage_6_0_0.bit1.dmux0 B2 ) ( storage_5_0_0.bit1.dmux0 B2 ) ( storage_4_0_0.bit1.dmux0 B2 ) ( storage_3_0_0.bit1.dmux0 B2 ) ( storage_2_0_0.bit1.dmux0 B2 ) ( storage_1_0_0.bit1.dmux0 B2 ) ++ ( storage_0_0_0.bit1.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal3 ( 750 903 ) ( 1130 * ) ++ NEW metal2 ( 750 903 ) ( * 1001 ) ++ NEW metal2 ( 1130 777 ) ( * 903 ) ++ NEW metal2 ( 1130 623 ) ( * 777 ) ++ NEW metal2 ( 1130 497 ) ( * 623 ) ++ NEW metal2 ( 1130 343 ) ( * 497 ) ++ NEW metal2 ( 1130 217 ) ( * 343 ) ++ NEW metal2 ( 1130 63 ) ( * 217 ) ++ NEW metal1 ( 1130 903 ) via1_4 ++ NEW metal2 ( 1130 903 ) via2_5 ++ NEW metal2 ( 750 903 ) via2_5 ++ NEW metal1 ( 750 1001 ) via1_7 ++ NEW metal1 ( 1130 777 ) via1_4 ++ NEW metal1 ( 1130 623 ) via1_4 ++ NEW metal1 ( 1130 497 ) via1_4 ++ NEW metal1 ( 1130 343 ) via1_4 ++ NEW metal1 ( 1130 217 ) via1_4 ++ NEW metal1 ( 1130 63 ) via1_4 ; ++ - D1_nets.b2 ( buffer1.in[2] Z ) ( storage_6_0_0.bit2.dmux0 B2 ) ( storage_5_0_0.bit2.dmux0 B2 ) ( storage_4_0_0.bit2.dmux0 B2 ) ( storage_3_0_0.bit2.dmux0 B2 ) ( storage_2_0_0.bit2.dmux0 B2 ) ( storage_1_0_0.bit2.dmux0 B2 ) ++ ( storage_0_0_0.bit2.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal2 ( 1377 903 ) ( * 1001 ) ++ NEW metal2 ( 1757 777 ) ( * 903 ) ++ NEW metal2 ( 1757 623 ) ( * 777 ) ++ NEW metal2 ( 1757 497 ) ( * 623 ) ++ NEW metal2 ( 1757 343 ) ( * 497 ) ++ NEW metal2 ( 1757 217 ) ( * 343 ) ++ NEW metal2 ( 1757 63 ) ( * 217 ) ++ NEW metal3 ( 1377 903 ) ( 1757 * ) ++ NEW metal2 ( 1377 903 ) via2_5 ++ NEW metal1 ( 1377 1001 ) via1_7 ++ NEW metal1 ( 1757 903 ) via1_4 ++ NEW metal2 ( 1757 903 ) via2_5 ++ NEW metal1 ( 1757 777 ) via1_4 ++ NEW metal1 ( 1757 623 ) via1_4 ++ NEW metal1 ( 1757 497 ) via1_4 ++ NEW metal1 ( 1757 343 ) via1_4 ++ NEW metal1 ( 1757 217 ) via1_4 ++ NEW metal1 ( 1757 63 ) via1_4 ; ++ - D1_nets.b3 ( buffer1.in[3] Z ) ( storage_6_0_0.bit3.dmux0 B2 ) ( storage_5_0_0.bit3.dmux0 B2 ) ( storage_4_0_0.bit3.dmux0 B2 ) ( storage_3_0_0.bit3.dmux0 B2 ) ( storage_2_0_0.bit3.dmux0 B2 ) ( storage_1_0_0.bit3.dmux0 B2 ) ++ ( storage_0_0_0.bit3.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal3 ( 2004 903 ) ( 2384 * ) ++ NEW metal2 ( 2004 903 ) ( * 1001 ) ++ NEW metal2 ( 2384 777 ) ( * 903 ) ++ NEW metal2 ( 2384 623 ) ( * 777 ) ++ NEW metal2 ( 2384 497 ) ( * 623 ) ++ NEW metal2 ( 2384 343 ) ( * 497 ) ++ NEW metal2 ( 2384 217 ) ( * 343 ) ++ NEW metal2 ( 2384 63 ) ( * 217 ) ++ NEW metal1 ( 2384 903 ) via1_4 ++ NEW metal2 ( 2384 903 ) via2_5 ++ NEW metal2 ( 2004 903 ) via2_5 ++ NEW metal1 ( 2004 1001 ) via1_7 ++ NEW metal1 ( 2384 777 ) via1_4 ++ NEW metal1 ( 2384 623 ) via1_4 ++ NEW metal1 ( 2384 497 ) via1_4 ++ NEW metal1 ( 2384 343 ) via1_4 ++ NEW metal1 ( 2384 217 ) via1_4 ++ NEW metal1 ( 2384 63 ) via1_4 ; ++ - D1_nets.b4 ( buffer1.in[4] Z ) ( storage_6_0_0.bit4.dmux0 B2 ) ( storage_5_0_0.bit4.dmux0 B2 ) ( storage_4_0_0.bit4.dmux0 B2 ) ( storage_3_0_0.bit4.dmux0 B2 ) ( storage_2_0_0.bit4.dmux0 B2 ) ( storage_1_0_0.bit4.dmux0 B2 ) ++ ( storage_0_0_0.bit4.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal3 ( 2631 903 ) ( 3011 * ) ++ NEW metal2 ( 2631 903 ) ( * 1001 ) ++ NEW metal2 ( 3011 777 ) ( * 903 ) ++ NEW metal2 ( 3011 623 ) ( * 777 ) ++ NEW metal2 ( 3011 497 ) ( * 623 ) ++ NEW metal2 ( 3011 343 ) ( * 497 ) ++ NEW metal2 ( 3011 217 ) ( * 343 ) ++ NEW metal2 ( 3011 63 ) ( * 217 ) ++ NEW metal1 ( 3011 903 ) via1_4 ++ NEW metal2 ( 3011 903 ) via2_5 ++ NEW metal2 ( 2631 903 ) via2_5 ++ NEW metal1 ( 2631 1001 ) via1_7 ++ NEW metal1 ( 3011 777 ) via1_4 ++ NEW metal1 ( 3011 623 ) via1_4 ++ NEW metal1 ( 3011 497 ) via1_4 ++ NEW metal1 ( 3011 343 ) via1_4 ++ NEW metal1 ( 3011 217 ) via1_4 ++ NEW metal1 ( 3011 63 ) via1_4 ; ++ - D1_nets.b5 ( buffer1.in[5] Z ) ( storage_6_0_0.bit5.dmux0 B2 ) ( storage_5_0_0.bit5.dmux0 B2 ) ( storage_4_0_0.bit5.dmux0 B2 ) ( storage_3_0_0.bit5.dmux0 B2 ) ( storage_2_0_0.bit5.dmux0 B2 ) ( storage_1_0_0.bit5.dmux0 B2 ) ++ ( storage_0_0_0.bit5.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal2 ( 3638 777 ) ( * 903 ) ++ NEW metal2 ( 3638 623 ) ( * 777 ) ++ NEW metal2 ( 3638 497 ) ( * 623 ) ++ NEW metal2 ( 3638 343 ) ( * 497 ) ++ NEW metal2 ( 3638 217 ) ( * 343 ) ++ NEW metal2 ( 3638 63 ) ( * 217 ) ++ NEW metal2 ( 3258 903 ) ( * 1001 ) ++ NEW metal3 ( 3258 903 ) ( 3638 * ) ++ NEW metal1 ( 3638 903 ) via1_4 ++ NEW metal2 ( 3638 903 ) via2_5 ++ NEW metal1 ( 3638 777 ) via1_4 ++ NEW metal1 ( 3638 623 ) via1_4 ++ NEW metal1 ( 3638 497 ) via1_4 ++ NEW metal1 ( 3638 343 ) via1_4 ++ NEW metal1 ( 3638 217 ) via1_4 ++ NEW metal1 ( 3638 63 ) via1_4 ++ NEW metal2 ( 3258 903 ) via2_5 ++ NEW metal1 ( 3258 1001 ) via1_7 ; ++ - D1_nets.b6 ( buffer1.in[6] Z ) ( storage_6_0_0.bit6.dmux0 B2 ) ( storage_5_0_0.bit6.dmux0 B2 ) ( storage_4_0_0.bit6.dmux0 B2 ) ( storage_3_0_0.bit6.dmux0 B2 ) ( storage_2_0_0.bit6.dmux0 B2 ) ( storage_1_0_0.bit6.dmux0 B2 ) ++ ( storage_0_0_0.bit6.dmux0 B2 ) + USE SIGNAL ++ + ROUTED metal3 ( 3885 903 ) ( 4265 * ) ++ NEW metal2 ( 3885 903 ) ( * 1001 ) ++ NEW metal2 ( 4265 777 ) ( * 903 ) ++ NEW metal2 ( 4265 623 ) ( * 777 ) ++ NEW metal2 ( 4265 497 ) ( * 623 ) ++ NEW metal2 ( 4265 343 ) ( * 497 ) ++ NEW metal2 ( 4265 217 ) ( * 343 ) ++ NEW metal2 ( 4265 63 ) ( * 217 ) ++ NEW metal1 ( 4265 903 ) via1_4 ++ NEW metal2 ( 4265 903 ) via2_5 ++ NEW metal2 ( 3885 903 ) via2_5 ++ NEW metal1 ( 3885 1001 ) via1_7 ++ NEW metal1 ( 4265 777 ) via1_4 ++ NEW metal1 ( 4265 623 ) via1_4 ++ NEW metal1 ( 4265 497 ) via1_4 ++ NEW metal1 ( 4265 343 ) via1_4 ++ NEW metal1 ( 4265 217 ) via1_4 ++ NEW metal1 ( 4265 63 ) via1_4 ; ++ - Q[0] ( PIN Q[0] ) ( storage_6_0_0.bit0.obuf0 Z ) ( storage_5_0_0.bit0.obuf0 Z ) ( storage_4_0_0.bit0.obuf0 Z ) ( storage_3_0_0.bit0.obuf0 Z ) ( storage_2_0_0.bit0.obuf0 Z ) ( storage_1_0_0.bit0.obuf0 Z ) ++ ( storage_0_0_0.bit0.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 345 945 ) ( 351 * ) ++ NEW metal4 ( 345 945 ) ( * 1113 0 ) ++ NEW metal2 ( 351 805 ) ( * 945 ) ++ NEW metal2 ( 351 665 ) ( * 805 ) ++ NEW metal2 ( 351 525 ) ( * 665 ) ++ NEW metal2 ( 351 385 ) ( * 525 ) ++ NEW metal2 ( 351 245 ) ( * 385 ) ++ NEW metal2 ( 351 105 ) ( * 245 ) ++ NEW metal1 ( 351 945 ) via1_4 ++ NEW metal2 ( 351 945 ) via2_5 ++ NEW metal3 ( 345 945 ) via3_2 ++ NEW metal1 ( 351 805 ) via1_4 ++ NEW metal1 ( 351 665 ) via1_4 ++ NEW metal1 ( 351 525 ) via1_4 ++ NEW metal1 ( 351 385 ) via1_4 ++ NEW metal1 ( 351 245 ) via1_4 ++ NEW metal1 ( 351 105 ) via1_4 ; ++ - Q[1] ( PIN Q[1] ) ( storage_6_0_0.bit1.obuf0 Z ) ( storage_5_0_0.bit1.obuf0 Z ) ( storage_4_0_0.bit1.obuf0 Z ) ( storage_3_0_0.bit1.obuf0 Z ) ( storage_2_0_0.bit1.obuf0 Z ) ( storage_1_0_0.bit1.obuf0 Z ) ++ ( storage_0_0_0.bit1.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 961 945 ) ( 978 * ) ++ NEW metal4 ( 961 945 ) ( * 1113 0 ) ++ NEW metal2 ( 978 805 ) ( * 945 ) ++ NEW metal2 ( 978 665 ) ( * 805 ) ++ NEW metal2 ( 978 525 ) ( * 665 ) ++ NEW metal2 ( 978 385 ) ( * 525 ) ++ NEW metal2 ( 978 245 ) ( * 385 ) ++ NEW metal2 ( 978 105 ) ( * 245 ) ++ NEW metal1 ( 978 945 ) via1_4 ++ NEW metal2 ( 978 945 ) via2_5 ++ NEW metal3 ( 961 945 ) via3_2 ++ NEW metal1 ( 978 805 ) via1_4 ++ NEW metal1 ( 978 665 ) via1_4 ++ NEW metal1 ( 978 525 ) via1_4 ++ NEW metal1 ( 978 385 ) via1_4 ++ NEW metal1 ( 978 245 ) via1_4 ++ NEW metal1 ( 978 105 ) via1_4 ; ++ - Q[2] ( PIN Q[2] ) ( storage_6_0_0.bit2.obuf0 Z ) ( storage_5_0_0.bit2.obuf0 Z ) ( storage_4_0_0.bit2.obuf0 Z ) ( storage_3_0_0.bit2.obuf0 Z ) ( storage_2_0_0.bit2.obuf0 Z ) ( storage_1_0_0.bit2.obuf0 Z ) ++ ( storage_0_0_0.bit2.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 1577 945 ) ( 1605 * ) ++ NEW metal4 ( 1577 945 ) ( * 1113 0 ) ++ NEW metal2 ( 1605 805 ) ( * 945 ) ++ NEW metal2 ( 1605 665 ) ( * 805 ) ++ NEW metal2 ( 1605 525 ) ( * 665 ) ++ NEW metal2 ( 1605 385 ) ( * 525 ) ++ NEW metal2 ( 1605 245 ) ( * 385 ) ++ NEW metal2 ( 1605 105 ) ( * 245 ) ++ NEW metal1 ( 1605 945 ) via1_4 ++ NEW metal2 ( 1605 945 ) via2_5 ++ NEW metal3 ( 1577 945 ) via3_2 ++ NEW metal1 ( 1605 805 ) via1_4 ++ NEW metal1 ( 1605 665 ) via1_4 ++ NEW metal1 ( 1605 525 ) via1_4 ++ NEW metal1 ( 1605 385 ) via1_4 ++ NEW metal1 ( 1605 245 ) via1_4 ++ NEW metal1 ( 1605 105 ) via1_4 ; ++ - Q[3] ( PIN Q[3] ) ( storage_6_0_0.bit3.obuf0 Z ) ( storage_5_0_0.bit3.obuf0 Z ) ( storage_4_0_0.bit3.obuf0 Z ) ( storage_3_0_0.bit3.obuf0 Z ) ( storage_2_0_0.bit3.obuf0 Z ) ( storage_1_0_0.bit3.obuf0 Z ) ++ ( storage_0_0_0.bit3.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 2193 945 ) ( 2232 * ) ++ NEW metal4 ( 2193 945 ) ( * 1113 0 ) ++ NEW metal2 ( 2232 805 ) ( * 945 ) ++ NEW metal2 ( 2232 665 ) ( * 805 ) ++ NEW metal2 ( 2232 525 ) ( * 665 ) ++ NEW metal2 ( 2232 385 ) ( * 525 ) ++ NEW metal2 ( 2232 245 ) ( * 385 ) ++ NEW metal2 ( 2232 105 ) ( * 245 ) ++ NEW metal1 ( 2232 945 ) via1_4 ++ NEW metal2 ( 2232 945 ) via2_5 ++ NEW metal3 ( 2193 945 ) via3_2 ++ NEW metal1 ( 2232 805 ) via1_4 ++ NEW metal1 ( 2232 665 ) via1_4 ++ NEW metal1 ( 2232 525 ) via1_4 ++ NEW metal1 ( 2232 385 ) via1_4 ++ NEW metal1 ( 2232 245 ) via1_4 ++ NEW metal1 ( 2232 105 ) via1_4 ; ++ - Q[4] ( PIN Q[4] ) ( storage_6_0_0.bit4.obuf0 Z ) ( storage_5_0_0.bit4.obuf0 Z ) ( storage_4_0_0.bit4.obuf0 Z ) ( storage_3_0_0.bit4.obuf0 Z ) ( storage_2_0_0.bit4.obuf0 Z ) ( storage_1_0_0.bit4.obuf0 Z ) ++ ( storage_0_0_0.bit4.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 2859 945 ) ( 2865 * ) ++ NEW metal4 ( 2865 945 ) ( * 1113 0 ) ++ NEW metal2 ( 2859 805 ) ( * 945 ) ++ NEW metal2 ( 2859 665 ) ( * 805 ) ++ NEW metal2 ( 2859 525 ) ( * 665 ) ++ NEW metal2 ( 2859 385 ) ( * 525 ) ++ NEW metal2 ( 2859 245 ) ( * 385 ) ++ NEW metal2 ( 2859 105 ) ( * 245 ) ++ NEW metal1 ( 2859 945 ) via1_4 ++ NEW metal2 ( 2859 945 ) via2_5 ++ NEW metal3 ( 2865 945 ) via3_2 ++ NEW metal1 ( 2859 805 ) via1_4 ++ NEW metal1 ( 2859 665 ) via1_4 ++ NEW metal1 ( 2859 525 ) via1_4 ++ NEW metal1 ( 2859 385 ) via1_4 ++ NEW metal1 ( 2859 245 ) via1_4 ++ NEW metal1 ( 2859 105 ) via1_4 ; ++ - Q[5] ( PIN Q[5] ) ( storage_6_0_0.bit5.obuf0 Z ) ( storage_5_0_0.bit5.obuf0 Z ) ( storage_4_0_0.bit5.obuf0 Z ) ( storage_3_0_0.bit5.obuf0 Z ) ( storage_2_0_0.bit5.obuf0 Z ) ( storage_1_0_0.bit5.obuf0 Z ) ++ ( storage_0_0_0.bit5.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 3481 945 ) ( 3486 * ) ++ NEW metal4 ( 3481 945 ) ( * 1113 0 ) ++ NEW metal2 ( 3486 805 ) ( * 945 ) ++ NEW metal2 ( 3486 665 ) ( * 805 ) ++ NEW metal2 ( 3486 525 ) ( * 665 ) ++ NEW metal2 ( 3486 385 ) ( * 525 ) ++ NEW metal2 ( 3486 245 ) ( * 385 ) ++ NEW metal2 ( 3486 105 ) ( * 245 ) ++ NEW metal1 ( 3486 945 ) via1_4 ++ NEW metal2 ( 3486 945 ) via2_5 ++ NEW metal3 ( 3481 945 ) via3_2 ++ NEW metal1 ( 3486 805 ) via1_4 ++ NEW metal1 ( 3486 665 ) via1_4 ++ NEW metal1 ( 3486 525 ) via1_4 ++ NEW metal1 ( 3486 385 ) via1_4 ++ NEW metal1 ( 3486 245 ) via1_4 ++ NEW metal1 ( 3486 105 ) via1_4 ; ++ - Q[6] ( PIN Q[6] ) ( storage_6_0_0.bit6.obuf0 Z ) ( storage_5_0_0.bit6.obuf0 Z ) ( storage_4_0_0.bit6.obuf0 Z ) ( storage_3_0_0.bit6.obuf0 Z ) ( storage_2_0_0.bit6.obuf0 Z ) ( storage_1_0_0.bit6.obuf0 Z ) ++ ( storage_0_0_0.bit6.obuf0 Z ) + USE SIGNAL ++ + ROUTED metal3 ( 4097 945 ) ( 4113 * ) ++ NEW metal4 ( 4097 945 ) ( * 1113 0 ) ++ NEW metal2 ( 4113 805 ) ( * 945 ) ++ NEW metal2 ( 4113 665 ) ( * 805 ) ++ NEW metal2 ( 4113 525 ) ( * 665 ) ++ NEW metal2 ( 4113 385 ) ( * 525 ) ++ NEW metal2 ( 4113 245 ) ( * 385 ) ++ NEW metal2 ( 4113 105 ) ( * 245 ) ++ NEW metal1 ( 4113 945 ) via1_4 ++ NEW metal2 ( 4113 945 ) via2_5 ++ NEW metal3 ( 4097 945 ) via3_2 ++ NEW metal1 ( 4113 805 ) via1_4 ++ NEW metal1 ( 4113 665 ) via1_4 ++ NEW metal1 ( 4113 525 ) via1_4 ++ NEW metal1 ( 4113 385 ) via1_4 ++ NEW metal1 ( 4113 245 ) via1_4 ++ NEW metal1 ( 4113 105 ) via1_4 ; ++ - addr_r0.inv_addr[0] ( decoder_p2.inv_p2_a0 ZN ) ( decoder_p2.and_layer0_word6 A1 ) ( decoder_p2.and_layer0_word4 A1 ) ( decoder_p2.and_layer0_word2 A1 ) ( decoder_p2.and_layer0_word0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5538 343 ) ( * 469 ) ++ NEW metal2 ( 5519 469 ) ( 5538 * ) ++ NEW metal2 ( 5538 63 ) ( * 189 ) ++ NEW metal2 ( 5519 189 ) ( 5538 * ) ++ NEW metal2 ( 5519 189 ) ( * 259 ) ++ NEW metal2 ( 5519 259 ) ( 5538 * ) ++ NEW metal2 ( 5538 259 ) ( * 343 ) ++ NEW metal2 ( 5538 623 ) ( * 651 ) ++ NEW metal2 ( 5500 651 ) ( 5538 * ) ++ NEW metal2 ( 5500 651 ) ( * 805 ) ++ NEW metal2 ( 5500 805 ) ( 5538 * ) ++ NEW metal2 ( 5538 805 ) ( * 903 ) ++ NEW metal3 ( 5538 665 ) ( 5747 * ) ++ NEW metal2 ( 5538 651 ) ( * 665 ) ++ NEW metal2 ( 5519 469 ) ( * 651 ) ++ NEW metal1 ( 5538 343 ) via1_4 ++ NEW metal1 ( 5538 63 ) via1_4 ++ NEW metal1 ( 5538 623 ) via1_4 ++ NEW metal1 ( 5538 903 ) via1_4 ++ NEW metal1 ( 5747 665 ) via1_4 ++ NEW metal2 ( 5747 665 ) via2_5 ++ NEW metal2 ( 5538 665 ) via2_5 ; ++ - addr_r0.inv_addr[1] ( decoder_p2.inv_p2_a1 ZN ) ( decoder_p2.and_layer1_word5 A1 ) ( decoder_p2.and_layer1_word4 A1 ) ( decoder_p2.and_layer1_word1 A1 ) ( decoder_p2.and_layer1_word0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5747 399 ) ( * 525 ) ++ NEW metal3 ( 5633 525 ) ( 5747 * ) ++ NEW metal2 ( 5614 217 ) ( * 273 ) ++ NEW metal3 ( 5614 273 ) ( 5747 * ) ++ NEW metal2 ( 5747 273 ) ( * 301 ) ++ NEW metal2 ( 5614 63 ) ( * 217 ) ++ NEW metal2 ( 5633 525 ) ( * 570 ) ++ NEW metal2 ( 5614 623 ) ( * 777 ) ++ NEW metal2 ( 5614 570 ) ( 5633 * ) ++ NEW metal2 ( 5614 570 ) ( * 623 ) ++ NEW metal1 ( 5747 399 ) via1_7 ++ NEW metal2 ( 5747 525 ) via2_5 ++ NEW metal2 ( 5633 525 ) via2_5 ++ NEW metal1 ( 5614 217 ) via1_4 ++ NEW metal2 ( 5614 273 ) via2_5 ++ NEW metal2 ( 5747 273 ) via2_5 ++ NEW metal1 ( 5747 301 ) via1_7 ++ NEW metal1 ( 5614 63 ) via1_4 ++ NEW metal1 ( 5614 623 ) via1_4 ++ NEW metal1 ( 5614 777 ) via1_4 ; ++ - addr_r0.inv_addr[2] ( decoder_p2.inv_p2_a2 ZN ) ( decoder_p2.and_layer1_word3 A2 ) ( decoder_p2.and_layer1_word2 A2 ) ( decoder_p2.and_layer1_word1 A2 ) ( decoder_p2.and_layer1_word0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5633 63 ) ( * 91 ) ++ NEW metal2 ( 5633 91 ) ( 5747 * ) ++ NEW metal2 ( 5633 91 ) ( * 217 ) ++ NEW metal2 ( 5633 217 ) ( * 343 ) ++ NEW metal2 ( 5633 343 ) ( * 497 ) ++ NEW metal1 ( 5633 63 ) via1_4 ++ NEW metal1 ( 5747 91 ) via1_4 ++ NEW metal1 ( 5633 217 ) via1_4 ++ NEW metal1 ( 5633 343 ) via1_4 ++ NEW metal1 ( 5633 497 ) via1_4 ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word5 A1 ) ( decoder_p2.and_layer0_word3 A1 ) ( decoder_p2.and_layer0_word1 A1 ) + USE SIGNAL ++ + ROUTED metal3 ( 5538 497 ) ( 5576 * ) ++ NEW metal2 ( 5576 245 ) ( * 497 ) ++ NEW metal2 ( 5538 245 ) ( 5576 * ) ++ NEW metal2 ( 5538 217 ) ( * 245 ) ++ NEW metal3 ( 5576 567 ) ( 5728 * ) ++ NEW metal3 ( 5576 315 ) ( 5753 * 0 ) ++ NEW metal2 ( 5538 749 ) ( 5576 * ) ++ NEW metal2 ( 5538 749 ) ( * 777 ) ++ NEW metal2 ( 5576 497 ) ( * 749 ) ++ NEW metal2 ( 5728 567 ) ( * 623 ) ++ NEW metal1 ( 5538 497 ) via1_4 ++ NEW metal2 ( 5538 497 ) via2_5 ++ NEW metal2 ( 5576 497 ) via2_5 ++ NEW metal1 ( 5538 217 ) via1_4 ++ NEW metal2 ( 5728 567 ) via2_5 ++ NEW metal2 ( 5576 567 ) via2_5 ++ NEW metal2 ( 5576 315 ) via2_5 ++ NEW metal1 ( 5728 623 ) via1_4 ++ NEW metal1 ( 5538 777 ) via1_4 ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word6 A1 ) ( decoder_p2.and_layer1_word3 A1 ) ( decoder_p2.and_layer1_word2 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5728 350 ) ( * 399 ) ++ NEW metal3 ( 5728 399 ) ( 5753 * 0 ) ++ NEW metal3 ( 5614 343 ) ( 5693 * ) ++ NEW metal3 ( 5693 329 ) ( * 343 ) ++ NEW metal3 ( 5693 329 ) ( 5747 * ) ++ NEW metal2 ( 5747 329 ) ( * 343 ) ++ NEW metal2 ( 5728 343 ) ( 5747 * ) ++ NEW metal2 ( 5728 343 ) ( * 350 ) ++ NEW metal2 ( 5614 343 ) ( * 497 ) ++ NEW metal3 ( 5614 511 ) ( 5652 * ) ++ NEW metal2 ( 5614 497 ) ( * 511 ) ++ NEW metal3 ( 5614 903 ) ( 5652 * ) ++ NEW metal2 ( 5652 511 ) ( * 903 ) ++ NEW metal1 ( 5728 350 ) via1_4 ++ NEW metal2 ( 5728 399 ) via2_5 ++ NEW metal1 ( 5614 343 ) via1_4 ++ NEW metal2 ( 5614 343 ) via2_5 ++ NEW metal2 ( 5747 329 ) via2_5 ++ NEW metal1 ( 5614 497 ) via1_4 ++ NEW metal2 ( 5652 511 ) via2_5 ++ NEW metal2 ( 5614 511 ) via2_5 ++ NEW metal2 ( 5652 903 ) via2_5 ++ NEW metal1 ( 5614 903 ) via1_4 ++ NEW metal2 ( 5614 903 ) via2_5 ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word6 A2 ) ( decoder_p2.and_layer1_word5 A2 ) ( decoder_p2.and_layer1_word4 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5500 91 ) ( 5753 * 0 ) ++ NEW metal3 ( 5721 63 ) ( 5728 * ) ++ NEW metal3 ( 5721 63 ) ( * 91 ) ++ NEW metal3 ( 5500 623 ) ( 5633 * ) ++ NEW metal2 ( 5633 623 ) ( * 777 ) ++ NEW metal2 ( 5633 777 ) ( * 903 ) ++ NEW metal2 ( 5500 91 ) ( * 623 ) ++ NEW metal2 ( 5500 91 ) via2_5 ++ NEW metal1 ( 5728 63 ) via1_4 ++ NEW metal2 ( 5728 63 ) via2_5 ++ NEW metal1 ( 5633 623 ) via1_4 ++ NEW metal2 ( 5633 623 ) via2_5 ++ NEW metal2 ( 5500 623 ) via2_5 ++ NEW metal1 ( 5633 777 ) via1_4 ++ NEW metal1 ( 5633 903 ) via1_4 ; ++ - addr_w0.inv_addr[0] ( decoder_p0.inv_p0_a0 ZN ) ( decoder_p0.and_layer0_word6 A1 ) ( decoder_p0.and_layer0_word4 A1 ) ( decoder_p0.and_layer0_word2 A1 ) ( decoder_p0.and_layer0_word0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5101 343 ) ( * 469 ) ++ NEW metal2 ( 5082 469 ) ( 5101 * ) ++ NEW metal2 ( 5082 469 ) ( * 525 ) ++ NEW metal2 ( 5082 525 ) ( 5101 * ) ++ NEW metal2 ( 5101 63 ) ( * 189 ) ++ NEW metal2 ( 5082 189 ) ( 5101 * ) ++ NEW metal2 ( 5082 189 ) ( * 245 ) ++ NEW metal2 ( 5082 245 ) ( 5101 * ) ++ NEW metal2 ( 5101 245 ) ( * 343 ) ++ NEW metal2 ( 5101 623 ) ( * 637 ) ++ NEW metal3 ( 5101 637 ) ( 5709 * ) ++ NEW metal2 ( 5101 833 ) ( * 903 ) ++ NEW metal2 ( 5082 833 ) ( 5101 * ) ++ NEW metal2 ( 5082 749 ) ( * 833 ) ++ NEW metal2 ( 5082 749 ) ( 5101 * ) ++ NEW metal2 ( 5101 637 ) ( * 749 ) ++ NEW metal2 ( 5101 525 ) ( * 623 ) ++ NEW metal1 ( 5101 343 ) via1_4 ++ NEW metal1 ( 5101 63 ) via1_4 ++ NEW metal1 ( 5101 623 ) via1_4 ++ NEW metal2 ( 5101 637 ) via2_5 ++ NEW metal1 ( 5709 637 ) via1_4 ++ NEW metal2 ( 5709 637 ) via2_5 ++ NEW metal1 ( 5101 903 ) via1_4 ; ++ - addr_w0.inv_addr[1] ( decoder_p0.inv_p0_a1 ZN ) ( decoder_p0.and_layer1_word5 A1 ) ( decoder_p0.and_layer1_word4 A1 ) ( decoder_p0.and_layer1_word1 A1 ) ( decoder_p0.and_layer1_word0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5177 217 ) ( * 301 ) ++ NEW metal3 ( 5177 301 ) ( 5709 * ) ++ NEW metal2 ( 5177 63 ) ( * 217 ) ++ NEW metal3 ( 5139 301 ) ( 5177 * ) ++ NEW metal2 ( 5177 623 ) ( * 777 ) ++ NEW metal2 ( 5139 623 ) ( 5177 * ) ++ NEW metal2 ( 5139 301 ) ( * 623 ) ++ NEW metal1 ( 5177 217 ) via1_4 ++ NEW metal2 ( 5177 301 ) via2_5 ++ NEW metal1 ( 5709 301 ) via1_7 ++ NEW metal2 ( 5709 301 ) via2_5 ++ NEW metal1 ( 5177 63 ) via1_4 ++ NEW metal2 ( 5139 301 ) via2_5 ++ NEW metal1 ( 5177 623 ) via1_4 ++ NEW metal1 ( 5177 777 ) via1_4 ; ++ - addr_w0.inv_addr[2] ( decoder_p0.inv_p0_a2 ZN ) ( decoder_p0.and_layer1_word3 A2 ) ( decoder_p0.and_layer1_word2 A2 ) ( decoder_p0.and_layer1_word1 A2 ) ( decoder_p0.and_layer1_word0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5196 49 ) ( * 63 ) ++ NEW metal3 ( 5196 49 ) ( 5709 * ) ++ NEW metal2 ( 5196 63 ) ( * 217 ) ++ NEW metal2 ( 5196 217 ) ( * 343 ) ++ NEW metal2 ( 5196 343 ) ( * 497 ) ++ NEW metal1 ( 5196 63 ) via1_4 ++ NEW metal2 ( 5196 49 ) via2_5 ++ NEW metal1 ( 5709 49 ) via1_4 ++ NEW metal2 ( 5709 49 ) via2_5 ++ NEW metal1 ( 5196 217 ) via1_4 ++ NEW metal1 ( 5196 343 ) via1_4 ++ NEW metal1 ( 5196 497 ) via1_4 ; ++ - addr_w0[0] ( PIN addr_w0[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word5 A1 ) ( decoder_p0.and_layer0_word3 A1 ) ( decoder_p0.and_layer0_word1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5690 469 ) ( 5709 * ) ++ NEW metal2 ( 5690 413 ) ( * 469 ) ++ NEW metal2 ( 5690 413 ) ( 5709 * ) ++ NEW metal2 ( 5709 329 ) ( * 413 ) ++ NEW metal2 ( 5709 329 ) ( 5728 * ) ++ NEW metal2 ( 5728 231 ) ( * 329 ) ++ NEW metal3 ( 5728 231 ) ( 5753 * 0 ) ++ NEW metal3 ( 5063 231 ) ( 5728 * ) ++ NEW metal3 ( 5063 497 ) ( 5101 * ) ++ NEW metal3 ( 5101 217 ) ( * 231 ) ++ NEW metal2 ( 5709 469 ) ( * 570 ) ++ NEW metal2 ( 5690 570 ) ( 5709 * ) ++ NEW metal2 ( 5690 570 ) ( * 623 ) ++ NEW metal3 ( 5063 777 ) ( 5101 * ) ++ NEW metal2 ( 5063 231 ) ( * 777 ) ++ NEW metal2 ( 5728 231 ) via2_5 ++ NEW metal2 ( 5063 231 ) via2_5 ++ NEW metal1 ( 5101 497 ) via1_4 ++ NEW metal2 ( 5101 497 ) via2_5 ++ NEW metal2 ( 5063 497 ) via2_5 ++ NEW metal1 ( 5101 217 ) via1_4 ++ NEW metal2 ( 5101 217 ) via2_5 ++ NEW metal1 ( 5690 623 ) via1_4 ++ NEW metal2 ( 5063 777 ) via2_5 ++ NEW metal1 ( 5101 777 ) via1_4 ++ NEW metal2 ( 5101 777 ) via2_5 ; ++ - addr_w0[1] ( PIN addr_w0[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word6 A1 ) ( decoder_p0.and_layer1_word3 A1 ) ( decoder_p0.and_layer1_word2 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5690 343 ) ( * 357 ) ++ NEW metal3 ( 5690 357 ) ( 5747 * ) ++ NEW metal3 ( 5747 343 ) ( * 357 ) ++ NEW metal3 ( 5747 343 ) ( 5753 * 0 ) ++ NEW metal2 ( 5177 343 ) ( * 357 ) ++ NEW metal3 ( 5177 357 ) ( 5690 * ) ++ NEW metal2 ( 5177 357 ) ( * 497 ) ++ NEW metal2 ( 5177 497 ) ( * 570 ) ++ NEW metal2 ( 5177 570 ) ( 5215 * ) ++ NEW metal2 ( 5215 570 ) ( * 931 ) ++ NEW metal2 ( 5177 931 ) ( 5215 * ) ++ NEW metal2 ( 5177 903 ) ( * 931 ) ++ NEW metal1 ( 5690 343 ) via1_4 ++ NEW metal2 ( 5690 357 ) via2_5 ++ NEW metal1 ( 5177 343 ) via1_4 ++ NEW metal2 ( 5177 357 ) via2_5 ++ NEW metal1 ( 5177 497 ) via1_4 ++ NEW metal1 ( 5177 903 ) via1_4 ; ++ - addr_w0[2] ( PIN addr_w0[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word6 A2 ) ( decoder_p0.and_layer1_word5 A2 ) ( decoder_p0.and_layer1_word4 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5272 63 ) ( 5690 * ) ++ NEW metal3 ( 5749 63 ) ( 5753 * 0 ) ++ NEW metal3 ( 5749 35 ) ( * 63 ) ++ NEW metal3 ( 5690 35 ) ( 5749 * ) ++ NEW metal2 ( 5690 35 ) ( * 63 ) ++ NEW metal3 ( 5196 623 ) ( 5272 * ) ++ NEW metal2 ( 5196 623 ) ( * 777 ) ++ NEW metal2 ( 5196 777 ) ( * 903 ) ++ NEW metal2 ( 5272 63 ) ( * 623 ) ++ NEW metal1 ( 5690 63 ) via1_4 ++ NEW metal2 ( 5690 63 ) via2_5 ++ NEW metal2 ( 5272 63 ) via2_5 ++ NEW metal2 ( 5690 35 ) via2_5 ++ NEW metal1 ( 5196 623 ) via1_4 ++ NEW metal2 ( 5196 623 ) via2_5 ++ NEW metal2 ( 5272 623 ) via2_5 ++ NEW metal1 ( 5196 777 ) via1_4 ++ NEW metal1 ( 5196 903 ) via1_4 ; ++ - addr_w1.inv_addr[0] ( decoder_p1.inv_p1_a0 ZN ) ( decoder_p1.and_layer0_word6 A1 ) ( decoder_p1.and_layer0_word4 A1 ) ( decoder_p1.and_layer0_word2 A1 ) ( decoder_p1.and_layer0_word0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5329 350 ) ( * 371 ) ++ NEW metal2 ( 5310 371 ) ( 5329 * ) ++ NEW metal2 ( 5310 63 ) ( 5329 * ) ++ NEW metal2 ( 5310 63 ) ( * 371 ) ++ NEW metal2 ( 5329 819 ) ( * 903 ) ++ NEW metal3 ( 5329 819 ) ( 5709 * ) ++ NEW metal2 ( 5310 623 ) ( 5329 * ) ++ NEW metal2 ( 5310 623 ) ( * 819 ) ++ NEW metal2 ( 5310 819 ) ( 5329 * ) ++ NEW metal2 ( 5310 371 ) ( * 623 ) ++ NEW metal1 ( 5329 350 ) via1_4 ++ NEW metal1 ( 5329 63 ) via1_4 ++ NEW metal1 ( 5329 903 ) via1_4 ++ NEW metal2 ( 5329 819 ) via2_5 ++ NEW metal1 ( 5709 819 ) via1_7 ++ NEW metal2 ( 5709 819 ) via2_5 ++ NEW metal1 ( 5329 623 ) via1_4 ; ++ - addr_w1.inv_addr[1] ( decoder_p1.inv_p1_a1 ZN ) ( decoder_p1.and_layer1_word5 A1 ) ( decoder_p1.and_layer1_word4 A1 ) ( decoder_p1.and_layer1_word1 A1 ) ( decoder_p1.and_layer1_word0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5405 63 ) ( * 217 ) ++ NEW metal4 ( 5357 189 ) ( * 441 ) ++ NEW metal3 ( 5357 189 ) ( 5405 * ) ++ NEW metal2 ( 5405 581 ) ( * 623 ) ++ NEW metal2 ( 5367 581 ) ( 5405 * ) ++ NEW metal2 ( 5367 441 ) ( * 581 ) ++ NEW metal2 ( 5405 623 ) ( * 777 ) ++ NEW metal3 ( 5357 441 ) ( 5709 * ) ++ NEW metal1 ( 5709 441 ) via1_7 ++ NEW metal2 ( 5709 441 ) via2_5 ++ NEW metal1 ( 5405 217 ) via1_4 ++ NEW metal1 ( 5405 63 ) via1_4 ++ NEW metal3 ( 5357 441 ) via3_2 ++ NEW metal3 ( 5357 189 ) via3_2 ++ NEW metal2 ( 5405 189 ) via2_5 ++ NEW metal1 ( 5405 623 ) via1_4 ++ NEW metal2 ( 5367 441 ) via2_5 ++ NEW metal1 ( 5405 777 ) via1_4 ; ++ - addr_w1.inv_addr[2] ( decoder_p1.inv_p1_a2 ZN ) ( decoder_p1.and_layer1_word3 A2 ) ( decoder_p1.and_layer1_word2 A2 ) ( decoder_p1.and_layer1_word1 A2 ) ( decoder_p1.and_layer1_word0 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5424 217 ) ( 5709 * ) ++ NEW metal2 ( 5424 217 ) ( * 343 ) ++ NEW metal2 ( 5424 63 ) ( * 217 ) ++ NEW metal2 ( 5424 343 ) ( * 497 ) ++ NEW metal1 ( 5424 217 ) via1_4 ++ NEW metal2 ( 5424 217 ) via2_5 ++ NEW metal1 ( 5709 217 ) via1_4 ++ NEW metal2 ( 5709 217 ) via2_5 ++ NEW metal1 ( 5424 343 ) via1_4 ++ NEW metal1 ( 5424 63 ) via1_4 ++ NEW metal1 ( 5424 497 ) via1_4 ; ++ - addr_w1[0] ( PIN addr_w1[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word5 A1 ) ( decoder_p1.and_layer0_word3 A1 ) ( decoder_p1.and_layer0_word1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 5443 595 ) ( * 777 ) ++ NEW metal2 ( 5329 497 ) ( * 595 ) ++ NEW metal4 ( 5329 259 ) ( * 399 ) ++ NEW metal2 ( 5329 399 ) ( * 497 ) ++ NEW metal2 ( 5329 217 ) ( * 259 ) ++ NEW metal3 ( 5329 259 ) ( 5753 * 0 ) ++ NEW metal3 ( 5329 595 ) ( 5443 * ) ++ NEW metal3 ( 5329 777 ) ( 5690 * ) ++ NEW metal1 ( 5690 777 ) via1_4 ++ NEW metal2 ( 5690 777 ) via2_5 ++ NEW metal2 ( 5443 595 ) via2_5 ++ NEW metal2 ( 5443 777 ) via2_5 ++ NEW metal1 ( 5329 497 ) via1_4 ++ NEW metal2 ( 5329 595 ) via2_5 ++ NEW metal3 ( 5329 259 ) via3_2 ++ NEW metal2 ( 5329 399 ) via2_5 ++ NEW metal3 ( 5329 399 ) via3_2 ++ NEW metal1 ( 5329 217 ) via1_4 ++ NEW metal2 ( 5329 259 ) via2_5 ++ NEW metal1 ( 5329 777 ) via1_4 ++ NEW metal2 ( 5329 777 ) via2_5 ; ++ - addr_w1[1] ( PIN addr_w1[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word6 A1 ) ( decoder_p1.and_layer1_word3 A1 ) ( decoder_p1.and_layer1_word2 A1 ) + USE SIGNAL ++ + ROUTED metal3 ( 5690 497 ) ( 5728 * ) ++ NEW metal2 ( 5728 427 ) ( * 497 ) ++ NEW metal3 ( 5709 427 ) ( 5728 * ) ++ NEW metal3 ( 5709 371 ) ( * 427 ) ++ NEW metal3 ( 5709 371 ) ( 5753 * 0 ) ++ NEW metal2 ( 5405 497 ) ( * 511 ) ++ NEW metal3 ( 5405 511 ) ( 5595 * ) ++ NEW metal3 ( 5595 497 ) ( * 511 ) ++ NEW metal3 ( 5595 497 ) ( 5690 * ) ++ NEW metal2 ( 5405 343 ) ( * 497 ) ++ NEW metal2 ( 5443 511 ) ( * 570 ) ++ NEW metal2 ( 5443 570 ) ( 5462 * ) ++ NEW metal2 ( 5462 570 ) ( * 581 ) ++ NEW metal3 ( 5462 581 ) ( * 609 ) ++ NEW metal3 ( 5367 609 ) ( 5462 * ) ++ NEW metal2 ( 5367 609 ) ( * 903 ) ++ NEW metal2 ( 5367 903 ) ( 5405 * ) ++ NEW metal1 ( 5690 497 ) via1_4 ++ NEW metal2 ( 5690 497 ) via2_5 ++ NEW metal2 ( 5728 497 ) via2_5 ++ NEW metal2 ( 5728 427 ) via2_5 ++ NEW metal1 ( 5405 497 ) via1_4 ++ NEW metal2 ( 5405 511 ) via2_5 ++ NEW metal1 ( 5405 343 ) via1_4 ++ NEW metal2 ( 5443 511 ) via2_5 ++ NEW metal2 ( 5462 581 ) via2_5 ++ NEW metal2 ( 5367 609 ) via2_5 ++ NEW metal1 ( 5405 903 ) via1_4 ; ++ - addr_w1[2] ( PIN addr_w1[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word6 A2 ) ( decoder_p1.and_layer1_word5 A2 ) ( decoder_p1.and_layer1_word4 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5443 287 ) ( 5753 * 0 ) ++ NEW metal2 ( 5443 287 ) ( * 469 ) ++ NEW metal2 ( 5443 469 ) ( 5462 * ) ++ NEW metal2 ( 5462 469 ) ( * 525 ) ++ NEW metal3 ( 5424 525 ) ( 5462 * ) ++ NEW metal2 ( 5690 217 ) ( * 287 ) ++ NEW metal2 ( 5424 777 ) ( * 903 ) ++ NEW metal2 ( 5424 623 ) ( * 777 ) ++ NEW metal2 ( 5424 581 ) ( 5427 * ) ++ NEW metal2 ( 5427 581 ) ( * 609 ) ++ NEW metal2 ( 5424 609 ) ( 5427 * ) ++ NEW metal2 ( 5424 609 ) ( * 623 ) ++ NEW metal2 ( 5424 525 ) ( * 581 ) ++ NEW metal2 ( 5443 287 ) via2_5 ++ NEW metal2 ( 5462 525 ) via2_5 ++ NEW metal2 ( 5424 525 ) via2_5 ++ NEW metal1 ( 5690 217 ) via1_4 ++ NEW metal2 ( 5690 287 ) via2_5 ++ NEW metal1 ( 5424 777 ) via1_4 ++ NEW metal1 ( 5424 903 ) via1_4 ++ NEW metal1 ( 5424 623 ) via1_4 ; ++ - clk ( PIN clk ) ( storage_6_0_0.cg CK ) ( storage_5_0_0.cg CK ) ( storage_4_0_0.cg CK ) ( storage_3_0_0.cg CK ) ( storage_2_0_0.cg CK ) ( storage_1_0_0.cg CK ) ++ ( storage_0_0_0.cg CK ) + USE SIGNAL ++ + ROUTED metal2 ( 4911 49 ) ( * 231 ) ++ NEW metal2 ( 4911 231 ) ( * 329 ) ++ NEW metal2 ( 4911 329 ) ( * 511 ) ++ NEW metal3 ( 4881 889 ) ( 4911 * ) ++ NEW metal4 ( 4881 889 ) ( * 1113 0 ) ++ NEW metal2 ( 4911 791 ) ( * 889 ) ++ NEW metal2 ( 4911 609 ) ( * 791 ) ++ NEW metal2 ( 4911 511 ) ( * 609 ) ++ NEW metal1 ( 4911 231 ) via1_7 ++ NEW metal1 ( 4911 49 ) via1_7 ++ NEW metal1 ( 4911 329 ) via1_7 ++ NEW metal1 ( 4911 511 ) via1_7 ++ NEW metal1 ( 4911 889 ) via1_7 ++ NEW metal2 ( 4911 889 ) via2_5 ++ NEW metal3 ( 4881 889 ) via3_2 ++ NEW metal1 ( 4911 791 ) via1_7 ++ NEW metal1 ( 4911 609 ) via1_7 ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 ZN ) ( decoder_p0.and_layer0_word0 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5120 63 ) ( 5234 * ) ++ NEW metal1 ( 5120 63 ) via1_4 ++ NEW metal2 ( 5120 63 ) via2_5 ++ NEW metal1 ( 5234 63 ) via1_4 ++ NEW metal2 ( 5234 63 ) via2_5 ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 ZN ) ( decoder_p0.and_layer0_word1 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5120 203 ) ( * 217 ) ++ NEW metal3 ( 5120 203 ) ( 5234 * ) ++ NEW metal1 ( 5120 217 ) via1_4 ++ NEW metal2 ( 5120 203 ) via2_5 ++ NEW metal1 ( 5234 203 ) via1_4 ++ NEW metal2 ( 5234 203 ) via2_5 ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 ZN ) ( decoder_p0.and_layer0_word2 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5120 343 ) ( 5234 * ) ++ NEW metal1 ( 5120 343 ) via1_4 ++ NEW metal2 ( 5120 343 ) via2_5 ++ NEW metal1 ( 5234 343 ) via1_4 ++ NEW metal2 ( 5234 343 ) via2_5 ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 ZN ) ( decoder_p0.and_layer0_word3 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5120 497 ) ( * 511 ) ++ NEW metal3 ( 5120 511 ) ( 5234 * ) ++ NEW metal1 ( 5120 497 ) via1_4 ++ NEW metal2 ( 5120 511 ) via2_5 ++ NEW metal1 ( 5234 511 ) via1_4 ++ NEW metal2 ( 5234 511 ) via2_5 ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 ZN ) ( decoder_p0.and_layer0_word4 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5120 609 ) ( * 623 ) ++ NEW metal3 ( 5120 609 ) ( 5234 * ) ++ NEW metal1 ( 5120 623 ) via1_4 ++ NEW metal2 ( 5120 609 ) via2_5 ++ NEW metal1 ( 5234 609 ) via1_4 ++ NEW metal2 ( 5234 609 ) via2_5 ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 ZN ) ( decoder_p0.and_layer0_word5 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5120 777 ) ( * 791 ) ++ NEW metal3 ( 5120 791 ) ( 5234 * ) ++ NEW metal1 ( 5120 777 ) via1_4 ++ NEW metal2 ( 5120 791 ) via2_5 ++ NEW metal1 ( 5234 791 ) via1_4 ++ NEW metal2 ( 5234 791 ) via2_5 ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 ZN ) ( decoder_p0.and_layer0_word6 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5120 903 ) ( 5234 * ) ++ NEW metal1 ( 5120 903 ) via1_4 ++ NEW metal2 ( 5120 903 ) via2_5 ++ NEW metal1 ( 5234 903 ) via1_4 ++ NEW metal2 ( 5234 903 ) via2_5 ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 ZN ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 63 ) ( * 77 ) ++ NEW metal3 ( 5044 77 ) ( 5158 * ) ++ NEW metal1 ( 5044 63 ) via1_4 ++ NEW metal2 ( 5044 77 ) via2_5 ++ NEW metal1 ( 5158 77 ) via1_4 ++ NEW metal2 ( 5158 77 ) via2_5 ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 ZN ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 217 ) ( * 245 ) ++ NEW metal3 ( 5044 245 ) ( 5158 * ) ++ NEW metal1 ( 5044 217 ) via1_4 ++ NEW metal2 ( 5044 245 ) via2_5 ++ NEW metal1 ( 5158 245 ) via1_4 ++ NEW metal2 ( 5158 245 ) via2_5 ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 ZN ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 329 ) ( * 343 ) ++ NEW metal3 ( 5044 329 ) ( 5158 * ) ++ NEW metal1 ( 5044 343 ) via1_4 ++ NEW metal2 ( 5044 329 ) via2_5 ++ NEW metal1 ( 5158 329 ) via1_4 ++ NEW metal2 ( 5158 329 ) via2_5 ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 ZN ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 483 ) ( * 497 ) ++ NEW metal3 ( 5044 483 ) ( 5158 * ) ++ NEW metal1 ( 5044 497 ) via1_4 ++ NEW metal2 ( 5044 483 ) via2_5 ++ NEW metal1 ( 5158 483 ) via1_4 ++ NEW metal2 ( 5158 483 ) via2_5 ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 ZN ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 623 ) ( * 651 ) ++ NEW metal3 ( 5044 651 ) ( 5158 * ) ++ NEW metal1 ( 5044 623 ) via1_4 ++ NEW metal2 ( 5044 651 ) via2_5 ++ NEW metal1 ( 5158 651 ) via1_4 ++ NEW metal2 ( 5158 651 ) via2_5 ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 ZN ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 763 ) ( * 777 ) ++ NEW metal3 ( 5044 763 ) ( 5158 * ) ++ NEW metal1 ( 5044 777 ) via1_4 ++ NEW metal2 ( 5044 763 ) via2_5 ++ NEW metal1 ( 5158 763 ) via1_4 ++ NEW metal2 ( 5158 763 ) via2_5 ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 ZN ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5044 903 ) ( * 917 ) ++ NEW metal3 ( 5044 917 ) ( 5158 * ) ++ NEW metal1 ( 5044 903 ) via1_4 ++ NEW metal2 ( 5044 917 ) via2_5 ++ NEW metal1 ( 5158 917 ) via1_4 ++ NEW metal2 ( 5158 917 ) via2_5 ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 ZN ) ( decoder_p1.and_layer0_word0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5348 63 ) ( * 77 ) ++ NEW metal3 ( 5348 77 ) ( 5462 * ) ++ NEW metal1 ( 5348 63 ) via1_4 ++ NEW metal2 ( 5348 77 ) via2_5 ++ NEW metal1 ( 5462 77 ) via1_4 ++ NEW metal2 ( 5462 77 ) via2_5 ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 ZN ) ( decoder_p1.and_layer0_word1 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5348 203 ) ( * 217 ) ++ NEW metal3 ( 5348 203 ) ( 5462 * ) ++ NEW metal1 ( 5348 217 ) via1_4 ++ NEW metal2 ( 5348 203 ) via2_5 ++ NEW metal1 ( 5462 203 ) via1_4 ++ NEW metal2 ( 5462 203 ) via2_5 ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 ZN ) ( decoder_p1.and_layer0_word2 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5348 343 ) ( 5462 * ) ++ NEW metal1 ( 5462 343 ) via1_4 ++ NEW metal2 ( 5462 343 ) via2_5 ++ NEW metal1 ( 5348 343 ) via1_4 ++ NEW metal2 ( 5348 343 ) via2_5 ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 ZN ) ( decoder_p1.and_layer0_word3 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5348 427 ) ( * 497 ) ++ NEW metal3 ( 5348 427 ) ( 5462 * ) ++ NEW metal2 ( 5462 427 ) ( * 441 ) ++ NEW metal1 ( 5348 497 ) via1_4 ++ NEW metal2 ( 5348 427 ) via2_5 ++ NEW metal2 ( 5462 427 ) via2_5 ++ NEW metal1 ( 5462 441 ) via1_7 ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 ZN ) ( decoder_p1.and_layer0_word4 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5348 623 ) ( 5462 * ) ++ NEW metal1 ( 5348 623 ) via1_4 ++ NEW metal2 ( 5348 623 ) via2_5 ++ NEW metal1 ( 5462 623 ) via1_4 ++ NEW metal2 ( 5462 623 ) via2_5 ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 ZN ) ( decoder_p1.and_layer0_word5 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5348 777 ) ( * 791 ) ++ NEW metal3 ( 5348 791 ) ( 5462 * ) ++ NEW metal1 ( 5348 777 ) via1_4 ++ NEW metal2 ( 5348 791 ) via2_5 ++ NEW metal1 ( 5462 791 ) via1_4 ++ NEW metal2 ( 5462 791 ) via2_5 ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 ZN ) ( decoder_p1.and_layer0_word6 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 5348 903 ) ( 5462 * ) ++ NEW metal1 ( 5348 903 ) via1_4 ++ NEW metal2 ( 5348 903 ) via2_5 ++ NEW metal1 ( 5462 903 ) via1_4 ++ NEW metal2 ( 5462 903 ) via2_5 ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 ZN ) ( sel_buf_w_p1.sel_buf_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5253 63 ) ( * 91 ) ++ NEW metal3 ( 5253 91 ) ( 5386 * ) ++ NEW metal1 ( 5253 63 ) via1_4 ++ NEW metal2 ( 5253 91 ) via2_5 ++ NEW metal1 ( 5386 91 ) via1_4 ++ NEW metal2 ( 5386 91 ) via2_5 ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 ZN ) ( sel_buf_w_p1.sel_buf_1 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5253 217 ) ( * 245 ) ++ NEW metal3 ( 5253 245 ) ( 5386 * ) ++ NEW metal1 ( 5253 217 ) via1_4 ++ NEW metal2 ( 5253 245 ) via2_5 ++ NEW metal1 ( 5386 245 ) via1_4 ++ NEW metal2 ( 5386 245 ) via2_5 ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 ZN ) ( sel_buf_w_p1.sel_buf_2 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5253 329 ) ( * 343 ) ++ NEW metal3 ( 5253 329 ) ( 5386 * ) ++ NEW metal1 ( 5253 343 ) via1_4 ++ NEW metal2 ( 5253 329 ) via2_5 ++ NEW metal1 ( 5386 329 ) via1_4 ++ NEW metal2 ( 5386 329 ) via2_5 ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 ZN ) ( sel_buf_w_p1.sel_buf_3 A ) + USE SIGNAL ++ + ROUTED metal3 ( 5253 497 ) ( 5386 * ) ++ NEW metal1 ( 5253 497 ) via1_4 ++ NEW metal2 ( 5253 497 ) via2_5 ++ NEW metal1 ( 5386 497 ) via1_4 ++ NEW metal2 ( 5386 497 ) via2_5 ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 ZN ) ( sel_buf_w_p1.sel_buf_4 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5253 623 ) ( * 665 ) ++ NEW metal3 ( 5253 665 ) ( 5386 * ) ++ NEW metal1 ( 5253 623 ) via1_4 ++ NEW metal2 ( 5253 665 ) via2_5 ++ NEW metal1 ( 5386 665 ) via1_4 ++ NEW metal2 ( 5386 665 ) via2_5 ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 ZN ) ( sel_buf_w_p1.sel_buf_5 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5253 763 ) ( * 777 ) ++ NEW metal3 ( 5253 763 ) ( 5386 * ) ++ NEW metal1 ( 5253 777 ) via1_4 ++ NEW metal2 ( 5253 763 ) via2_5 ++ NEW metal1 ( 5386 763 ) via1_4 ++ NEW metal2 ( 5386 763 ) via2_5 ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 ZN ) ( sel_buf_w_p1.sel_buf_6 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5253 903 ) ( * 931 ) ++ NEW metal2 ( 5253 931 ) ( 5386 * ) ++ NEW metal1 ( 5253 903 ) via1_4 ++ NEW metal1 ( 5386 931 ) via1_4 ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 ZN ) ( decoder_p2.and_layer0_word0 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 21 ) ( * 63 ) ++ NEW metal3 ( 5557 21 ) ( 5671 * ) ++ NEW metal1 ( 5557 63 ) via1_4 ++ NEW metal2 ( 5557 21 ) via2_5 ++ NEW metal1 ( 5671 21 ) via1_7 ++ NEW metal2 ( 5671 21 ) via2_5 ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 ZN ) ( decoder_p2.and_layer0_word1 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 203 ) ( * 217 ) ++ NEW metal3 ( 5557 203 ) ( 5671 * ) ++ NEW metal1 ( 5557 217 ) via1_4 ++ NEW metal2 ( 5557 203 ) via2_5 ++ NEW metal1 ( 5671 203 ) via1_4 ++ NEW metal2 ( 5671 203 ) via2_5 ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 ZN ) ( decoder_p2.and_layer0_word2 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 329 ) ( * 343 ) ++ NEW metal3 ( 5557 329 ) ( 5671 * ) ++ NEW metal1 ( 5557 343 ) via1_4 ++ NEW metal2 ( 5557 329 ) via2_5 ++ NEW metal1 ( 5671 329 ) via1_4 ++ NEW metal2 ( 5671 329 ) via2_5 ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 ZN ) ( decoder_p2.and_layer0_word3 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 483 ) ( * 497 ) ++ NEW metal3 ( 5557 483 ) ( 5671 * ) ++ NEW metal1 ( 5557 497 ) via1_4 ++ NEW metal2 ( 5557 483 ) via2_5 ++ NEW metal1 ( 5671 483 ) via1_4 ++ NEW metal2 ( 5671 483 ) via2_5 ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 ZN ) ( decoder_p2.and_layer0_word4 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 609 ) ( * 623 ) ++ NEW metal3 ( 5557 609 ) ( 5671 * ) ++ NEW metal1 ( 5557 623 ) via1_4 ++ NEW metal2 ( 5557 609 ) via2_5 ++ NEW metal1 ( 5671 609 ) via1_4 ++ NEW metal2 ( 5671 609 ) via2_5 ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 ZN ) ( decoder_p2.and_layer0_word5 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 777 ) ( * 791 ) ++ NEW metal3 ( 5557 791 ) ( 5671 * ) ++ NEW metal1 ( 5557 777 ) via1_4 ++ NEW metal2 ( 5557 791 ) via2_5 ++ NEW metal1 ( 5671 791 ) via1_4 ++ NEW metal2 ( 5671 791 ) via2_5 ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 ZN ) ( decoder_p2.and_layer0_word6 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 5557 903 ) ( * 931 ) ++ NEW metal2 ( 5557 931 ) ( 5671 * ) ++ NEW metal1 ( 5557 903 ) via1_4 ++ NEW metal1 ( 5671 931 ) via1_4 ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 ZN ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 35 ) ( * 63 ) ++ NEW metal3 ( 5481 35 ) ( 5595 * ) ++ NEW metal1 ( 5481 63 ) via1_4 ++ NEW metal2 ( 5481 35 ) via2_5 ++ NEW metal1 ( 5595 35 ) via1_4 ++ NEW metal2 ( 5595 35 ) via2_5 ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 ZN ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 217 ) ( * 245 ) ++ NEW metal3 ( 5481 245 ) ( 5595 * ) ++ NEW metal1 ( 5481 217 ) via1_4 ++ NEW metal2 ( 5481 245 ) via2_5 ++ NEW metal1 ( 5595 245 ) via1_4 ++ NEW metal2 ( 5595 245 ) via2_5 ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 ZN ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 343 ) ( * 371 ) ++ NEW metal3 ( 5481 371 ) ( 5595 * ) ++ NEW metal1 ( 5481 343 ) via1_4 ++ NEW metal2 ( 5481 371 ) via2_5 ++ NEW metal1 ( 5595 371 ) via1_4 ++ NEW metal2 ( 5595 371 ) via2_5 ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 ZN ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 469 ) ( * 497 ) ++ NEW metal3 ( 5481 469 ) ( 5595 * ) ++ NEW metal1 ( 5481 497 ) via1_4 ++ NEW metal2 ( 5481 469 ) via2_5 ++ NEW metal1 ( 5595 469 ) via1_4 ++ NEW metal2 ( 5595 469 ) via2_5 ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 ZN ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 623 ) ( * 651 ) ++ NEW metal3 ( 5481 651 ) ( 5595 * ) ++ NEW metal1 ( 5481 623 ) via1_4 ++ NEW metal2 ( 5481 651 ) via2_5 ++ NEW metal1 ( 5595 651 ) via1_4 ++ NEW metal2 ( 5595 651 ) via2_5 ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 ZN ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 763 ) ( * 777 ) ++ NEW metal3 ( 5481 763 ) ( 5595 * ) ++ NEW metal1 ( 5481 777 ) via1_4 ++ NEW metal2 ( 5481 763 ) via2_5 ++ NEW metal1 ( 5595 763 ) via1_4 ++ NEW metal2 ( 5595 763 ) via2_5 ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 ZN ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5481 903 ) ( * 959 ) ++ NEW metal2 ( 5481 959 ) ( 5595 * ) ++ NEW metal1 ( 5481 903 ) via1_4 ++ NEW metal1 ( 5595 959 ) via1_7 ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Z ) ( storage_0_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 63 ) ( * 105 ) ++ NEW metal3 ( 5006 105 ) ( 5519 * ) ++ NEW metal1 ( 5006 63 ) via1_4 ++ NEW metal2 ( 5006 105 ) via2_5 ++ NEW metal1 ( 5519 105 ) via1_4 ++ NEW metal2 ( 5519 105 ) via2_5 ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Z ) ( storage_1_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 161 ) ( * 217 ) ++ NEW metal3 ( 5006 161 ) ( 5519 * ) ++ NEW metal1 ( 5006 217 ) via1_4 ++ NEW metal2 ( 5006 161 ) via2_5 ++ NEW metal1 ( 5519 161 ) via1_7 ++ NEW metal2 ( 5519 161 ) via2_5 ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Z ) ( storage_2_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 315 ) ( * 343 ) ++ NEW metal3 ( 5006 315 ) ( 5519 * ) ++ NEW metal1 ( 5006 343 ) via1_4 ++ NEW metal2 ( 5006 315 ) via2_5 ++ NEW metal1 ( 5519 315 ) via1_4 ++ NEW metal2 ( 5519 315 ) via2_5 ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Z ) ( storage_3_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 413 ) ( * 497 ) ++ NEW metal3 ( 5006 413 ) ( 5519 * ) ++ NEW metal2 ( 5519 413 ) ( * 441 ) ++ NEW metal1 ( 5006 497 ) via1_4 ++ NEW metal2 ( 5006 413 ) via2_5 ++ NEW metal2 ( 5519 413 ) via2_5 ++ NEW metal1 ( 5519 441 ) via1_7 ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Z ) ( storage_4_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 623 ) ( * 679 ) ++ NEW metal3 ( 5006 679 ) ( 5519 * ) ++ NEW metal1 ( 5006 623 ) via1_4 ++ NEW metal2 ( 5006 679 ) via2_5 ++ NEW metal1 ( 5519 679 ) via1_7 ++ NEW metal2 ( 5519 679 ) via2_5 ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Z ) ( storage_5_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 721 ) ( * 777 ) ++ NEW metal3 ( 5006 721 ) ( 5519 * ) ++ NEW metal1 ( 5006 777 ) via1_4 ++ NEW metal2 ( 5006 721 ) via2_5 ++ NEW metal1 ( 5519 721 ) via1_7 ++ NEW metal2 ( 5519 721 ) via2_5 ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Z ) ( storage_6_0_0.select_inv_0 A ) + USE SIGNAL ++ + ROUTED metal2 ( 5006 889 ) ( * 903 ) ++ NEW metal3 ( 5006 889 ) ( 5519 * ) ++ NEW metal1 ( 5006 903 ) via1_4 ++ NEW metal2 ( 5006 889 ) via2_5 ++ NEW metal1 ( 5519 889 ) via1_4 ++ NEW metal2 ( 5519 889 ) via2_5 ; ++ - storage_0_0_0.bit0.d ( storage_0_0_0.bit0.dmux0_inv ZN ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 104 63 ) ( 617 * ) ++ NEW metal1 ( 104 63 ) via1_4 ++ NEW metal2 ( 104 63 ) via2_5 ++ NEW metal1 ( 617 63 ) via1_4 ++ NEW metal2 ( 617 63 ) via2_5 ; ++ - storage_0_0_0.bit0.d_pair0_b ( storage_0_0_0.bit0.dmux0_inv A ) ( storage_0_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 63 ) ( * 77 ) ++ NEW metal3 ( 560 77 ) ( 598 * ) ++ NEW metal1 ( 598 63 ) via1_4 ++ NEW metal2 ( 598 77 ) via2_5 ++ NEW metal1 ( 560 77 ) via1_7 ++ NEW metal2 ( 560 77 ) via2_5 ; ++ - storage_0_0_0.bit0.storage ( storage_0_0_0.bit0.obuf0 A ) ( storage_0_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 332 63 ) ( 427 * ) ++ NEW metal1 ( 427 63 ) via1_4 ++ NEW metal1 ( 332 63 ) via1_4 ; ++ - storage_0_0_0.bit1.d ( storage_0_0_0.bit1.dmux0_inv ZN ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 731 63 ) ( 1244 * ) ++ NEW metal1 ( 731 63 ) via1_4 ++ NEW metal2 ( 731 63 ) via2_5 ++ NEW metal1 ( 1244 63 ) via1_4 ++ NEW metal2 ( 1244 63 ) via2_5 ; ++ - storage_0_0_0.bit1.d_pair0_b ( storage_0_0_0.bit1.dmux0_inv A ) ( storage_0_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 21 ) ( * 63 ) ++ NEW metal2 ( 1168 21 ) ( 1225 * ) ++ NEW metal1 ( 1225 63 ) via1_4 ++ NEW metal1 ( 1168 21 ) via1_7 ; ++ - storage_0_0_0.bit1.storage ( storage_0_0_0.bit1.obuf0 A ) ( storage_0_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 959 63 ) ( 1054 * ) ++ NEW metal1 ( 1054 63 ) via1_4 ++ NEW metal1 ( 959 63 ) via1_4 ; ++ - storage_0_0_0.bit2.d ( storage_0_0_0.bit2.dmux0_inv ZN ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1358 63 ) ( 1871 * ) ++ NEW metal1 ( 1358 63 ) via1_4 ++ NEW metal2 ( 1358 63 ) via2_5 ++ NEW metal1 ( 1871 63 ) via1_4 ++ NEW metal2 ( 1871 63 ) via2_5 ; ++ - storage_0_0_0.bit2.d_pair0_b ( storage_0_0_0.bit2.dmux0_inv A ) ( storage_0_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 21 ) ( * 63 ) ++ NEW metal2 ( 1795 21 ) ( 1852 * ) ++ NEW metal1 ( 1852 63 ) via1_4 ++ NEW metal1 ( 1795 21 ) via1_7 ; ++ - storage_0_0_0.bit2.storage ( storage_0_0_0.bit2.obuf0 A ) ( storage_0_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1586 63 ) ( 1681 * ) ++ NEW metal1 ( 1681 63 ) via1_4 ++ NEW metal1 ( 1586 63 ) via1_4 ; ++ - storage_0_0_0.bit3.d ( storage_0_0_0.bit3.dmux0_inv ZN ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1985 63 ) ( 2498 * ) ++ NEW metal1 ( 1985 63 ) via1_4 ++ NEW metal2 ( 1985 63 ) via2_5 ++ NEW metal1 ( 2498 63 ) via1_4 ++ NEW metal2 ( 2498 63 ) via2_5 ; ++ - storage_0_0_0.bit3.d_pair0_b ( storage_0_0_0.bit3.dmux0_inv A ) ( storage_0_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 21 ) ( * 63 ) ++ NEW metal2 ( 2422 21 ) ( 2479 * ) ++ NEW metal1 ( 2479 63 ) via1_4 ++ NEW metal1 ( 2422 21 ) via1_7 ; ++ - storage_0_0_0.bit3.storage ( storage_0_0_0.bit3.obuf0 A ) ( storage_0_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 63 ) ( * 77 ) ++ NEW metal3 ( 2213 77 ) ( 2308 * ) ++ NEW metal1 ( 2308 63 ) via1_4 ++ NEW metal2 ( 2308 77 ) via2_5 ++ NEW metal1 ( 2213 77 ) via1_4 ++ NEW metal2 ( 2213 77 ) via2_5 ; ++ - storage_0_0_0.bit4.d ( storage_0_0_0.bit4.dmux0_inv ZN ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 2612 63 ) ( 3125 * ) ++ NEW metal1 ( 2612 63 ) via1_4 ++ NEW metal2 ( 2612 63 ) via2_5 ++ NEW metal1 ( 3125 63 ) via1_4 ++ NEW metal2 ( 3125 63 ) via2_5 ; ++ - storage_0_0_0.bit4.d_pair0_b ( storage_0_0_0.bit4.dmux0_inv A ) ( storage_0_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 21 ) ( * 63 ) ++ NEW metal2 ( 3049 21 ) ( 3106 * ) ++ NEW metal1 ( 3106 63 ) via1_4 ++ NEW metal1 ( 3049 21 ) via1_7 ; ++ - storage_0_0_0.bit4.storage ( storage_0_0_0.bit4.obuf0 A ) ( storage_0_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 63 ) ( * 77 ) ++ NEW metal3 ( 2840 77 ) ( 2935 * ) ++ NEW metal1 ( 2935 63 ) via1_4 ++ NEW metal2 ( 2935 77 ) via2_5 ++ NEW metal1 ( 2840 77 ) via1_4 ++ NEW metal2 ( 2840 77 ) via2_5 ; ++ - storage_0_0_0.bit5.d ( storage_0_0_0.bit5.dmux0_inv ZN ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3239 63 ) ( 3752 * ) ++ NEW metal1 ( 3752 63 ) via1_4 ++ NEW metal2 ( 3752 63 ) via2_5 ++ NEW metal1 ( 3239 63 ) via1_4 ++ NEW metal2 ( 3239 63 ) via2_5 ; ++ - storage_0_0_0.bit5.d_pair0_b ( storage_0_0_0.bit5.dmux0_inv A ) ( storage_0_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 63 ) ( * 77 ) ++ NEW metal3 ( 3695 77 ) ( 3733 * ) ++ NEW metal1 ( 3733 63 ) via1_4 ++ NEW metal2 ( 3733 77 ) via2_5 ++ NEW metal1 ( 3695 77 ) via1_7 ++ NEW metal2 ( 3695 77 ) via2_5 ; ++ - storage_0_0_0.bit5.storage ( storage_0_0_0.bit5.obuf0 A ) ( storage_0_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3467 63 ) ( 3562 * ) ++ NEW metal1 ( 3562 63 ) via1_4 ++ NEW metal1 ( 3467 63 ) via1_4 ; ++ - storage_0_0_0.bit6.d ( storage_0_0_0.bit6.dmux0_inv ZN ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3866 63 ) ( 4379 * ) ++ NEW metal1 ( 3866 63 ) via1_4 ++ NEW metal2 ( 3866 63 ) via2_5 ++ NEW metal1 ( 4379 63 ) via1_4 ++ NEW metal2 ( 4379 63 ) via2_5 ; ++ - storage_0_0_0.bit6.d_pair0_b ( storage_0_0_0.bit6.dmux0_inv A ) ( storage_0_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 21 ) ( * 63 ) ++ NEW metal2 ( 4303 21 ) ( 4360 * ) ++ NEW metal1 ( 4360 63 ) via1_4 ++ NEW metal1 ( 4303 21 ) via1_7 ; ++ - storage_0_0_0.bit6.storage ( storage_0_0_0.bit6.obuf0 A ) ( storage_0_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4094 63 ) ( 4189 * ) ++ NEW metal1 ( 4189 63 ) via1_4 ++ NEW metal1 ( 4094 63 ) via1_4 ; ++ - storage_0_0_0.gclock ( storage_0_0_0.cg GCK ) ( storage_0_0_0.bit6.bit CK ) ( storage_0_0_0.bit5.bit CK ) ( storage_0_0_0.bit4.bit CK ) ( storage_0_0_0.bit3.bit CK ) ( storage_0_0_0.bit2.bit CK ) ( storage_0_0_0.bit1.bit CK ) ++ ( storage_0_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 63 ) ( * 91 ) ++ NEW metal2 ( 180 63 ) ( * 91 ) ++ NEW metal3 ( 180 91 ) ( 807 * ) ++ NEW metal2 ( 3942 49 ) ( * 63 ) ++ NEW metal2 ( 3942 63 ) ( * 91 ) ++ NEW metal2 ( 3315 63 ) ( * 91 ) ++ NEW metal2 ( 2688 63 ) ( * 91 ) ++ NEW metal3 ( 2688 91 ) ( 3315 * ) ++ NEW metal2 ( 2061 63 ) ( * 91 ) ++ NEW metal3 ( 2061 91 ) ( 2688 * ) ++ NEW metal2 ( 1434 63 ) ( * 91 ) ++ NEW metal3 ( 1434 91 ) ( 2061 * ) ++ NEW metal3 ( 807 91 ) ( 1434 * ) ++ NEW metal3 ( 3315 91 ) ( 3942 * ) ++ NEW metal3 ( 3942 49 ) ( 4987 * ) ++ NEW metal1 ( 807 63 ) via1_4 ++ NEW metal2 ( 807 91 ) via2_5 ++ NEW metal1 ( 180 63 ) via1_4 ++ NEW metal2 ( 180 91 ) via2_5 ++ NEW metal1 ( 3942 63 ) via1_4 ++ NEW metal2 ( 3942 49 ) via2_5 ++ NEW metal2 ( 3942 91 ) via2_5 ++ NEW metal1 ( 3315 63 ) via1_4 ++ NEW metal2 ( 3315 91 ) via2_5 ++ NEW metal1 ( 2688 63 ) via1_4 ++ NEW metal2 ( 2688 91 ) via2_5 ++ NEW metal1 ( 2061 63 ) via1_4 ++ NEW metal2 ( 2061 91 ) via2_5 ++ NEW metal1 ( 1434 63 ) via1_4 ++ NEW metal2 ( 1434 91 ) via2_5 ++ NEW metal1 ( 4987 49 ) via1_4 ++ NEW metal2 ( 4987 49 ) via2_5 ; ++ - storage_0_0_0.later0_b ( storage_0_0_0.take_and0 A2 ) ( storage_0_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 63 ) ( * 91 ) ++ NEW metal2 ( 4588 91 ) ( 4626 * ) ++ NEW metal1 ( 4626 63 ) via1_4 ++ NEW metal1 ( 4588 91 ) via1_4 ; ++ - storage_0_0_0.select0_b ( storage_0_0_0.select_inv_0 ZN ) ( storage_0_0_0.bit6.obuf0 EN ) ( storage_0_0_0.bit5.obuf0 EN ) ( storage_0_0_0.bit4.obuf0 EN ) ( storage_0_0_0.bit3.obuf0 EN ) ( storage_0_0_0.bit2.obuf0 EN ) ( storage_0_0_0.bit1.obuf0 EN ) ++ ( storage_0_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal2 ( 1092 91 ) ( * 105 ) ++ NEW metal3 ( 465 105 ) ( 1092 * ) ++ NEW metal2 ( 465 91 ) ( * 105 ) ++ NEW metal2 ( 3600 91 ) ( * 105 ) ++ NEW metal3 ( 3600 105 ) ( 3985 * ) ++ NEW metal3 ( 3985 91 ) ( * 105 ) ++ NEW metal3 ( 3985 91 ) ( 4227 * ) ++ NEW metal2 ( 3600 49 ) ( * 91 ) ++ NEW metal2 ( 2973 49 ) ( * 77 ) ++ NEW metal2 ( 2346 49 ) ( * 77 ) ++ NEW metal3 ( 2346 49 ) ( 2973 * ) ++ NEW metal2 ( 1719 49 ) ( * 77 ) ++ NEW metal3 ( 1719 49 ) ( 2346 * ) ++ NEW metal2 ( 1719 77 ) ( * 105 ) ++ NEW metal3 ( 1092 105 ) ( 1719 * ) ++ NEW metal3 ( 2973 49 ) ( 3600 * ) ++ NEW metal3 ( 4227 91 ) ( 5025 * ) ++ NEW metal1 ( 1092 91 ) via1_4 ++ NEW metal2 ( 1092 105 ) via2_5 ++ NEW metal2 ( 465 105 ) via2_5 ++ NEW metal1 ( 465 91 ) via1_4 ++ NEW metal1 ( 4227 91 ) via1_4 ++ NEW metal2 ( 4227 91 ) via2_5 ++ NEW metal1 ( 3600 91 ) via1_4 ++ NEW metal2 ( 3600 105 ) via2_5 ++ NEW metal2 ( 3600 49 ) via2_5 ++ NEW metal1 ( 2973 77 ) via1_4 ++ NEW metal2 ( 2973 49 ) via2_5 ++ NEW metal1 ( 2346 77 ) via1_4 ++ NEW metal2 ( 2346 49 ) via2_5 ++ NEW metal1 ( 1719 77 ) via1_4 ++ NEW metal2 ( 1719 49 ) via2_5 ++ NEW metal2 ( 1719 105 ) via2_5 ++ NEW metal1 ( 5025 91 ) via1_4 ++ NEW metal2 ( 5025 91 ) via2_5 ; ++ - storage_0_0_0.take0 ( storage_0_0_0.bit6.dmux0 A1 ) ( storage_0_0_0.bit5.dmux0 A1 ) ( storage_0_0_0.bit4.dmux0 A1 ) ( storage_0_0_0.bit3.dmux0 A1 ) ( storage_0_0_0.bit2.dmux0 A1 ) ( storage_0_0_0.bit1.dmux0 A1 ) ( storage_0_0_0.bit0.dmux0 A1 ) ++ ( storage_0_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 560 49 ) ( 1187 * ) ++ NEW metal2 ( 3676 49 ) ( 3695 * ) ++ NEW metal2 ( 3676 49 ) ( * 119 ) ++ NEW metal2 ( 4322 49 ) ( * 119 ) ++ NEW metal3 ( 3676 119 ) ( 4322 * ) ++ NEW metal2 ( 3068 49 ) ( * 119 ) ++ NEW metal2 ( 2441 49 ) ( * 119 ) ++ NEW metal3 ( 2441 119 ) ( 3068 * ) ++ NEW metal2 ( 1814 49 ) ( * 119 ) ++ NEW metal3 ( 1814 119 ) ( 2441 * ) ++ NEW metal3 ( 1465 35 ) ( * 49 ) ++ NEW metal3 ( 1465 35 ) ( 1738 * ) ++ NEW metal2 ( 1738 35 ) ( * 119 ) ++ NEW metal3 ( 1738 119 ) ( 1814 * ) ++ NEW metal3 ( 1187 49 ) ( 1465 * ) ++ NEW metal3 ( 3068 119 ) ( 3676 * ) ++ NEW metal3 ( 4322 119 ) ( 4664 * ) ++ NEW metal1 ( 1187 49 ) via1_4 ++ NEW metal2 ( 1187 49 ) via2_5 ++ NEW metal1 ( 560 49 ) via1_4 ++ NEW metal2 ( 560 49 ) via2_5 ++ NEW metal1 ( 3695 49 ) via1_4 ++ NEW metal2 ( 3676 119 ) via2_5 ++ NEW metal1 ( 4322 49 ) via1_4 ++ NEW metal2 ( 4322 119 ) via2_5 ++ NEW metal1 ( 3068 49 ) via1_4 ++ NEW metal2 ( 3068 119 ) via2_5 ++ NEW metal1 ( 2441 49 ) via1_4 ++ NEW metal2 ( 2441 119 ) via2_5 ++ NEW metal1 ( 1814 49 ) via1_4 ++ NEW metal2 ( 1814 119 ) via2_5 ++ NEW metal2 ( 1738 35 ) via2_5 ++ NEW metal2 ( 1738 119 ) via2_5 ++ NEW metal1 ( 4664 119 ) via1_7 ++ NEW metal2 ( 4664 119 ) via2_5 ; ++ - storage_0_0_0.we ( storage_0_0_0.cg E ) ( storage_0_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 63 ) ( 4854 * ) ++ NEW metal1 ( 4854 63 ) via1_4 ++ NEW metal2 ( 4854 63 ) via2_5 ++ NEW metal1 ( 4740 63 ) via1_4 ++ NEW metal2 ( 4740 63 ) via2_5 ; ++ - storage_0_0_0.we0 ( storage_0_0_0.any_or0 A2 ) ( storage_0_0_0.take_and0 A1 ) ( storage_0_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 63 ) ( 4702 * ) ++ NEW metal3 ( 4474 63 ) ( 4607 * ) ++ NEW metal1 ( 4474 63 ) via1_4 ++ NEW metal2 ( 4474 63 ) via2_5 ++ NEW metal1 ( 4607 63 ) via1_4 ++ NEW metal2 ( 4607 63 ) via2_5 ++ NEW metal1 ( 4702 63 ) via1_4 ++ NEW metal2 ( 4702 63 ) via2_5 ; ++ - storage_0_0_0.we1 ( storage_0_0_0.bit6.dmux0 B1 ) ( storage_0_0_0.bit5.dmux0 B1 ) ( storage_0_0_0.bit4.dmux0 B1 ) ( storage_0_0_0.bit3.dmux0 B1 ) ( storage_0_0_0.bit2.dmux0 B1 ) ( storage_0_0_0.bit1.dmux0 B1 ) ( storage_0_0_0.bit0.dmux0 B1 ) ++ ( storage_0_0_0.any_or0 A1 ) ( storage_0_0_0.later_inv0 A ) ( storage_0_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 35 ) ( * 63 ) ++ NEW metal3 ( 522 35 ) ( 1149 * ) ++ NEW metal2 ( 522 35 ) ( * 63 ) ++ NEW metal2 ( 3657 21 ) ( * 63 ) ++ NEW metal2 ( 4284 21 ) ( * 63 ) ++ NEW metal3 ( 3657 21 ) ( 4284 * ) ++ NEW metal3 ( 4284 21 ) ( 4550 * ) ++ NEW metal2 ( 4550 21 ) ( * 63 ) ++ NEW metal3 ( 1149 35 ) ( 1425 * ) ++ NEW metal2 ( 3030 21 ) ( * 63 ) ++ NEW metal2 ( 2403 21 ) ( * 63 ) ++ NEW metal3 ( 2403 21 ) ( 3030 * ) ++ NEW metal2 ( 1776 21 ) ( * 63 ) ++ NEW metal3 ( 1776 21 ) ( 2403 * ) ++ NEW metal3 ( 1425 21 ) ( * 35 ) ++ NEW metal3 ( 1425 21 ) ( 1776 * ) ++ NEW metal3 ( 3030 21 ) ( 3657 * ) ++ NEW metal2 ( 4683 21 ) ( * 63 ) ++ NEW metal3 ( 4550 21 ) ( 4683 * ) ++ NEW metal2 ( 4550 63 ) ( 4569 * ) ++ NEW metal1 ( 1149 63 ) via1_4 ++ NEW metal2 ( 1149 35 ) via2_5 ++ NEW metal2 ( 522 35 ) via2_5 ++ NEW metal1 ( 522 63 ) via1_4 ++ NEW metal1 ( 3657 63 ) via1_4 ++ NEW metal2 ( 3657 21 ) via2_5 ++ NEW metal1 ( 4284 63 ) via1_4 ++ NEW metal2 ( 4284 21 ) via2_5 ++ NEW metal1 ( 4550 21 ) via1_7 ++ NEW metal2 ( 4550 21 ) via2_5 ++ NEW metal1 ( 3030 63 ) via1_4 ++ NEW metal2 ( 3030 21 ) via2_5 ++ NEW metal1 ( 2403 63 ) via1_4 ++ NEW metal2 ( 2403 21 ) via2_5 ++ NEW metal1 ( 1776 63 ) via1_4 ++ NEW metal2 ( 1776 21 ) via2_5 ++ NEW metal1 ( 4569 63 ) via1_4 ++ NEW metal2 ( 4683 21 ) via2_5 ++ NEW metal1 ( 4683 63 ) via1_4 ; ++ - storage_1_0_0.bit0.d ( storage_1_0_0.bit0.dmux0_inv ZN ) ( storage_1_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 104 217 ) ( 617 * ) ++ NEW metal1 ( 104 217 ) via1_4 ++ NEW metal2 ( 104 217 ) via2_5 ++ NEW metal1 ( 617 217 ) via1_4 ++ NEW metal2 ( 617 217 ) via2_5 ; ++ - storage_1_0_0.bit0.d_pair0_b ( storage_1_0_0.bit0.dmux0_inv A ) ( storage_1_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 203 ) ( * 217 ) ++ NEW metal3 ( 560 203 ) ( 598 * ) ++ NEW metal1 ( 598 217 ) via1_4 ++ NEW metal2 ( 598 203 ) via2_5 ++ NEW metal1 ( 560 203 ) via1_7 ++ NEW metal2 ( 560 203 ) via2_5 ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.obuf0 A ) ( storage_1_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 427 217 ) ( * 231 ) ++ NEW metal3 ( 332 231 ) ( 427 * ) ++ NEW metal1 ( 427 217 ) via1_4 ++ NEW metal2 ( 427 231 ) via2_5 ++ NEW metal1 ( 332 231 ) via1_4 ++ NEW metal2 ( 332 231 ) via2_5 ; ++ - storage_1_0_0.bit1.d ( storage_1_0_0.bit1.dmux0_inv ZN ) ( storage_1_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 731 217 ) ( 1244 * ) ++ NEW metal1 ( 731 217 ) via1_4 ++ NEW metal2 ( 731 217 ) via2_5 ++ NEW metal1 ( 1244 217 ) via1_4 ++ NEW metal2 ( 1244 217 ) via2_5 ; ++ - storage_1_0_0.bit1.d_pair0_b ( storage_1_0_0.bit1.dmux0_inv A ) ( storage_1_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 203 ) ( * 217 ) ++ NEW metal3 ( 1187 203 ) ( 1225 * ) ++ NEW metal1 ( 1225 217 ) via1_4 ++ NEW metal2 ( 1225 203 ) via2_5 ++ NEW metal1 ( 1187 203 ) via1_7 ++ NEW metal2 ( 1187 203 ) via2_5 ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.obuf0 A ) ( storage_1_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1054 217 ) ( * 231 ) ++ NEW metal3 ( 959 231 ) ( 1054 * ) ++ NEW metal1 ( 1054 217 ) via1_4 ++ NEW metal2 ( 1054 231 ) via2_5 ++ NEW metal1 ( 959 231 ) via1_4 ++ NEW metal2 ( 959 231 ) via2_5 ; ++ - storage_1_0_0.bit2.d ( storage_1_0_0.bit2.dmux0_inv ZN ) ( storage_1_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1358 217 ) ( 1871 * ) ++ NEW metal1 ( 1358 217 ) via1_4 ++ NEW metal2 ( 1358 217 ) via2_5 ++ NEW metal1 ( 1871 217 ) via1_4 ++ NEW metal2 ( 1871 217 ) via2_5 ; ++ - storage_1_0_0.bit2.d_pair0_b ( storage_1_0_0.bit2.dmux0_inv A ) ( storage_1_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 203 ) ( * 217 ) ++ NEW metal3 ( 1814 203 ) ( 1852 * ) ++ NEW metal1 ( 1852 217 ) via1_4 ++ NEW metal2 ( 1852 203 ) via2_5 ++ NEW metal1 ( 1814 203 ) via1_7 ++ NEW metal2 ( 1814 203 ) via2_5 ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.obuf0 A ) ( storage_1_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1681 217 ) ( * 231 ) ++ NEW metal3 ( 1586 231 ) ( 1681 * ) ++ NEW metal1 ( 1681 217 ) via1_4 ++ NEW metal2 ( 1681 231 ) via2_5 ++ NEW metal1 ( 1586 231 ) via1_4 ++ NEW metal2 ( 1586 231 ) via2_5 ; ++ - storage_1_0_0.bit3.d ( storage_1_0_0.bit3.dmux0_inv ZN ) ( storage_1_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1985 217 ) ( 2498 * ) ++ NEW metal1 ( 1985 217 ) via1_4 ++ NEW metal2 ( 1985 217 ) via2_5 ++ NEW metal1 ( 2498 217 ) via1_4 ++ NEW metal2 ( 2498 217 ) via2_5 ; ++ - storage_1_0_0.bit3.d_pair0_b ( storage_1_0_0.bit3.dmux0_inv A ) ( storage_1_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 203 ) ( * 217 ) ++ NEW metal3 ( 2441 203 ) ( 2479 * ) ++ NEW metal1 ( 2479 217 ) via1_4 ++ NEW metal2 ( 2479 203 ) via2_5 ++ NEW metal1 ( 2441 203 ) via1_7 ++ NEW metal2 ( 2441 203 ) via2_5 ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.obuf0 A ) ( storage_1_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 217 ) ( * 231 ) ++ NEW metal3 ( 2213 231 ) ( 2308 * ) ++ NEW metal1 ( 2308 217 ) via1_4 ++ NEW metal2 ( 2308 231 ) via2_5 ++ NEW metal1 ( 2213 231 ) via1_4 ++ NEW metal2 ( 2213 231 ) via2_5 ; ++ - storage_1_0_0.bit4.d ( storage_1_0_0.bit4.dmux0_inv ZN ) ( storage_1_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 2612 217 ) ( 3125 * ) ++ NEW metal1 ( 2612 217 ) via1_4 ++ NEW metal2 ( 2612 217 ) via2_5 ++ NEW metal1 ( 3125 217 ) via1_4 ++ NEW metal2 ( 3125 217 ) via2_5 ; ++ - storage_1_0_0.bit4.d_pair0_b ( storage_1_0_0.bit4.dmux0_inv A ) ( storage_1_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 203 ) ( * 217 ) ++ NEW metal3 ( 3068 203 ) ( 3106 * ) ++ NEW metal1 ( 3106 217 ) via1_4 ++ NEW metal2 ( 3106 203 ) via2_5 ++ NEW metal1 ( 3068 203 ) via1_7 ++ NEW metal2 ( 3068 203 ) via2_5 ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.obuf0 A ) ( storage_1_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 217 ) ( * 231 ) ++ NEW metal3 ( 2840 231 ) ( 2935 * ) ++ NEW metal1 ( 2935 217 ) via1_4 ++ NEW metal2 ( 2935 231 ) via2_5 ++ NEW metal1 ( 2840 231 ) via1_4 ++ NEW metal2 ( 2840 231 ) via2_5 ; ++ - storage_1_0_0.bit5.d ( storage_1_0_0.bit5.dmux0_inv ZN ) ( storage_1_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3239 217 ) ( 3752 * ) ++ NEW metal1 ( 3752 217 ) via1_4 ++ NEW metal2 ( 3752 217 ) via2_5 ++ NEW metal1 ( 3239 217 ) via1_4 ++ NEW metal2 ( 3239 217 ) via2_5 ; ++ - storage_1_0_0.bit5.d_pair0_b ( storage_1_0_0.bit5.dmux0_inv A ) ( storage_1_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 203 ) ( * 217 ) ++ NEW metal3 ( 3695 203 ) ( 3733 * ) ++ NEW metal1 ( 3733 217 ) via1_4 ++ NEW metal2 ( 3733 203 ) via2_5 ++ NEW metal1 ( 3695 203 ) via1_7 ++ NEW metal2 ( 3695 203 ) via2_5 ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.obuf0 A ) ( storage_1_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3562 217 ) ( * 231 ) ++ NEW metal3 ( 3467 231 ) ( 3562 * ) ++ NEW metal1 ( 3562 217 ) via1_4 ++ NEW metal2 ( 3562 231 ) via2_5 ++ NEW metal1 ( 3467 231 ) via1_4 ++ NEW metal2 ( 3467 231 ) via2_5 ; ++ - storage_1_0_0.bit6.d ( storage_1_0_0.bit6.dmux0_inv ZN ) ( storage_1_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3866 217 ) ( 4379 * ) ++ NEW metal1 ( 3866 217 ) via1_4 ++ NEW metal2 ( 3866 217 ) via2_5 ++ NEW metal1 ( 4379 217 ) via1_4 ++ NEW metal2 ( 4379 217 ) via2_5 ; ++ - storage_1_0_0.bit6.d_pair0_b ( storage_1_0_0.bit6.dmux0_inv A ) ( storage_1_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 203 ) ( * 217 ) ++ NEW metal3 ( 4322 203 ) ( 4360 * ) ++ NEW metal1 ( 4360 217 ) via1_4 ++ NEW metal2 ( 4360 203 ) via2_5 ++ NEW metal1 ( 4322 203 ) via1_7 ++ NEW metal2 ( 4322 203 ) via2_5 ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.obuf0 A ) ( storage_1_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4189 217 ) ( * 231 ) ++ NEW metal3 ( 4094 231 ) ( 4189 * ) ++ NEW metal1 ( 4189 217 ) via1_4 ++ NEW metal2 ( 4189 231 ) via2_5 ++ NEW metal1 ( 4094 231 ) via1_4 ++ NEW metal2 ( 4094 231 ) via2_5 ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCK ) ( storage_1_0_0.bit6.bit CK ) ( storage_1_0_0.bit5.bit CK ) ( storage_1_0_0.bit4.bit CK ) ( storage_1_0_0.bit3.bit CK ) ( storage_1_0_0.bit2.bit CK ) ( storage_1_0_0.bit1.bit CK ) ++ ( storage_1_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 217 ) ( * 245 ) ++ NEW metal2 ( 180 217 ) ( * 245 ) ++ NEW metal3 ( 180 245 ) ( 807 * ) ++ NEW metal2 ( 3942 217 ) ( * 245 ) ++ NEW metal2 ( 3315 217 ) ( * 245 ) ++ NEW metal2 ( 2688 217 ) ( * 245 ) ++ NEW metal3 ( 2688 245 ) ( 3315 * ) ++ NEW metal2 ( 2061 217 ) ( * 245 ) ++ NEW metal3 ( 2061 245 ) ( 2688 * ) ++ NEW metal2 ( 1434 217 ) ( * 245 ) ++ NEW metal3 ( 1434 245 ) ( 2061 * ) ++ NEW metal3 ( 807 245 ) ( 1434 * ) ++ NEW metal3 ( 3315 245 ) ( 3942 * ) ++ NEW metal3 ( 3942 245 ) ( 4987 * ) ++ NEW metal1 ( 807 217 ) via1_4 ++ NEW metal2 ( 807 245 ) via2_5 ++ NEW metal1 ( 180 217 ) via1_4 ++ NEW metal2 ( 180 245 ) via2_5 ++ NEW metal1 ( 3942 217 ) via1_4 ++ NEW metal2 ( 3942 245 ) via2_5 ++ NEW metal1 ( 3315 217 ) via1_4 ++ NEW metal2 ( 3315 245 ) via2_5 ++ NEW metal1 ( 2688 217 ) via1_4 ++ NEW metal2 ( 2688 245 ) via2_5 ++ NEW metal1 ( 2061 217 ) via1_4 ++ NEW metal2 ( 2061 245 ) via2_5 ++ NEW metal1 ( 1434 217 ) via1_4 ++ NEW metal2 ( 1434 245 ) via2_5 ++ NEW metal1 ( 4987 245 ) via1_4 ++ NEW metal2 ( 4987 245 ) via2_5 ; ++ - storage_1_0_0.later0_b ( storage_1_0_0.take_and0 A2 ) ( storage_1_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 217 ) ( * 245 ) ++ NEW metal2 ( 4588 245 ) ( 4626 * ) ++ NEW metal1 ( 4626 217 ) via1_4 ++ NEW metal1 ( 4588 245 ) via1_4 ; ++ - storage_1_0_0.select0_b ( storage_1_0_0.select_inv_0 ZN ) ( storage_1_0_0.bit6.obuf0 EN ) ( storage_1_0_0.bit5.obuf0 EN ) ( storage_1_0_0.bit4.obuf0 EN ) ( storage_1_0_0.bit3.obuf0 EN ) ( storage_1_0_0.bit2.obuf0 EN ) ( storage_1_0_0.bit1.obuf0 EN ) ++ ( storage_1_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal3 ( 465 189 ) ( 1092 * ) ++ NEW metal3 ( 3600 189 ) ( 4227 * ) ++ NEW metal3 ( 3453 175 ) ( * 189 ) ++ NEW metal3 ( 3453 189 ) ( 3600 * ) ++ NEW metal2 ( 2973 175 ) ( * 189 ) ++ NEW metal2 ( 2346 175 ) ( * 189 ) ++ NEW metal3 ( 2346 175 ) ( 2973 * ) ++ NEW metal2 ( 1719 175 ) ( * 189 ) ++ NEW metal3 ( 1719 175 ) ( 2346 * ) ++ NEW metal3 ( 1465 175 ) ( * 189 ) ++ NEW metal3 ( 1465 175 ) ( 1719 * ) ++ NEW metal3 ( 1092 189 ) ( 1465 * ) ++ NEW metal3 ( 2973 175 ) ( 3453 * ) ++ NEW metal3 ( 4227 189 ) ( 5025 * ) ++ NEW metal1 ( 1092 189 ) via1_4 ++ NEW metal2 ( 1092 189 ) via2_5 ++ NEW metal1 ( 465 189 ) via1_4 ++ NEW metal2 ( 465 189 ) via2_5 ++ NEW metal1 ( 4227 189 ) via1_4 ++ NEW metal2 ( 4227 189 ) via2_5 ++ NEW metal1 ( 3600 189 ) via1_4 ++ NEW metal2 ( 3600 189 ) via2_5 ++ NEW metal1 ( 2973 189 ) via1_4 ++ NEW metal2 ( 2973 175 ) via2_5 ++ NEW metal1 ( 2346 189 ) via1_4 ++ NEW metal2 ( 2346 175 ) via2_5 ++ NEW metal1 ( 1719 189 ) via1_4 ++ NEW metal2 ( 1719 175 ) via2_5 ++ NEW metal1 ( 5025 189 ) via1_4 ++ NEW metal2 ( 5025 189 ) via2_5 ; ++ - storage_1_0_0.take0 ( storage_1_0_0.bit6.dmux0 A1 ) ( storage_1_0_0.bit5.dmux0 A1 ) ( storage_1_0_0.bit4.dmux0 A1 ) ( storage_1_0_0.bit3.dmux0 A1 ) ( storage_1_0_0.bit2.dmux0 A1 ) ( storage_1_0_0.bit1.dmux0 A1 ) ( storage_1_0_0.bit0.dmux0 A1 ) ++ ( storage_1_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1187 231 ) ( * 259 ) ++ NEW metal3 ( 560 259 ) ( 1187 * ) ++ NEW metal2 ( 560 231 ) ( * 259 ) ++ NEW metal2 ( 3695 231 ) ( * 259 ) ++ NEW metal2 ( 4322 231 ) ( * 259 ) ++ NEW metal3 ( 3695 259 ) ( 4322 * ) ++ NEW metal2 ( 1814 231 ) ( * 259 ) ++ NEW metal2 ( 2441 231 ) ( * 259 ) ++ NEW metal3 ( 1814 259 ) ( 2441 * ) ++ NEW metal2 ( 3068 231 ) ( * 259 ) ++ NEW metal3 ( 2441 259 ) ( 3068 * ) ++ NEW metal3 ( 1187 259 ) ( 1814 * ) ++ NEW metal3 ( 3068 259 ) ( 3695 * ) ++ NEW metal3 ( 4322 259 ) ( 4664 * ) ++ NEW metal1 ( 1187 231 ) via1_4 ++ NEW metal2 ( 1187 259 ) via2_5 ++ NEW metal2 ( 560 259 ) via2_5 ++ NEW metal1 ( 560 231 ) via1_4 ++ NEW metal1 ( 3695 231 ) via1_4 ++ NEW metal2 ( 3695 259 ) via2_5 ++ NEW metal1 ( 4322 231 ) via1_4 ++ NEW metal2 ( 4322 259 ) via2_5 ++ NEW metal1 ( 1814 231 ) via1_4 ++ NEW metal2 ( 1814 259 ) via2_5 ++ NEW metal1 ( 2441 231 ) via1_4 ++ NEW metal2 ( 2441 259 ) via2_5 ++ NEW metal1 ( 3068 231 ) via1_4 ++ NEW metal2 ( 3068 259 ) via2_5 ++ NEW metal1 ( 4664 259 ) via1_7 ++ NEW metal2 ( 4664 259 ) via2_5 ; ++ - storage_1_0_0.we ( storage_1_0_0.cg E ) ( storage_1_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 217 ) ( 4854 * ) ++ NEW metal1 ( 4854 217 ) via1_4 ++ NEW metal2 ( 4854 217 ) via2_5 ++ NEW metal1 ( 4740 217 ) via1_4 ++ NEW metal2 ( 4740 217 ) via2_5 ; ++ - storage_1_0_0.we0 ( storage_1_0_0.any_or0 A2 ) ( storage_1_0_0.take_and0 A1 ) ( storage_1_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 217 ) ( 4702 * ) ++ NEW metal3 ( 4474 217 ) ( 4607 * ) ++ NEW metal1 ( 4474 217 ) via1_4 ++ NEW metal2 ( 4474 217 ) via2_5 ++ NEW metal1 ( 4607 217 ) via1_4 ++ NEW metal2 ( 4607 217 ) via2_5 ++ NEW metal1 ( 4702 217 ) via1_4 ++ NEW metal2 ( 4702 217 ) via2_5 ; ++ - storage_1_0_0.we1 ( storage_1_0_0.bit6.dmux0 B1 ) ( storage_1_0_0.bit5.dmux0 B1 ) ( storage_1_0_0.bit4.dmux0 B1 ) ( storage_1_0_0.bit3.dmux0 B1 ) ( storage_1_0_0.bit2.dmux0 B1 ) ( storage_1_0_0.bit1.dmux0 B1 ) ( storage_1_0_0.bit0.dmux0 B1 ) ++ ( storage_1_0_0.any_or0 A1 ) ( storage_1_0_0.later_inv0 A ) ( storage_1_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 175 ) ( * 217 ) ++ NEW metal3 ( 522 175 ) ( 1149 * ) ++ NEW metal2 ( 522 175 ) ( * 217 ) ++ NEW metal2 ( 3657 203 ) ( * 217 ) ++ NEW metal2 ( 4284 175 ) ( * 217 ) ++ NEW metal3 ( 3657 175 ) ( 4284 * ) ++ NEW metal2 ( 3657 175 ) ( * 203 ) ++ NEW metal3 ( 4284 175 ) ( 4550 * ) ++ NEW metal2 ( 4550 175 ) ( * 217 ) ++ NEW metal3 ( 1149 175 ) ( 1425 * ) ++ NEW metal3 ( 3420 203 ) ( 3657 * ) ++ NEW metal2 ( 1776 161 ) ( * 217 ) ++ NEW metal3 ( 1425 161 ) ( 1776 * ) ++ NEW metal3 ( 1425 161 ) ( * 175 ) ++ NEW metal2 ( 2403 161 ) ( * 217 ) ++ NEW metal3 ( 1776 161 ) ( 2403 * ) ++ NEW metal2 ( 3030 161 ) ( * 217 ) ++ NEW metal3 ( 2403 161 ) ( 3030 * ) ++ NEW metal3 ( 3420 189 ) ( * 203 ) ++ NEW metal3 ( 3030 189 ) ( 3420 * ) ++ NEW metal2 ( 4683 175 ) ( * 217 ) ++ NEW metal3 ( 4550 175 ) ( 4683 * ) ++ NEW metal2 ( 4550 217 ) ( 4569 * ) ++ NEW metal1 ( 1149 217 ) via1_4 ++ NEW metal2 ( 1149 175 ) via2_5 ++ NEW metal2 ( 522 175 ) via2_5 ++ NEW metal1 ( 522 217 ) via1_4 ++ NEW metal1 ( 3657 217 ) via1_4 ++ NEW metal2 ( 3657 203 ) via2_5 ++ NEW metal1 ( 4284 217 ) via1_4 ++ NEW metal2 ( 4284 175 ) via2_5 ++ NEW metal2 ( 3657 175 ) via2_5 ++ NEW metal1 ( 4550 175 ) via1_4 ++ NEW metal2 ( 4550 175 ) via2_5 ++ NEW metal1 ( 1776 217 ) via1_4 ++ NEW metal2 ( 1776 161 ) via2_5 ++ NEW metal1 ( 2403 217 ) via1_4 ++ NEW metal2 ( 2403 161 ) via2_5 ++ NEW metal1 ( 3030 217 ) via1_4 ++ NEW metal2 ( 3030 161 ) via2_5 ++ NEW metal2 ( 3030 189 ) via2_5 ++ NEW metal2 ( 4683 175 ) via2_5 ++ NEW metal1 ( 4683 217 ) via1_4 ++ NEW metal1 ( 4569 217 ) via1_4 ; ++ - storage_2_0_0.bit0.d ( storage_2_0_0.bit0.dmux0_inv ZN ) ( storage_2_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 104 343 ) ( 617 * ) ++ NEW metal1 ( 104 343 ) via1_4 ++ NEW metal2 ( 104 343 ) via2_5 ++ NEW metal1 ( 617 343 ) via1_4 ++ NEW metal2 ( 617 343 ) via2_5 ; ++ - storage_2_0_0.bit0.d_pair0_b ( storage_2_0_0.bit0.dmux0_inv A ) ( storage_2_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 343 ) ( * 357 ) ++ NEW metal3 ( 560 357 ) ( 598 * ) ++ NEW metal1 ( 598 343 ) via1_4 ++ NEW metal2 ( 598 357 ) via2_5 ++ NEW metal1 ( 560 357 ) via1_7 ++ NEW metal2 ( 560 357 ) via2_5 ; ++ - storage_2_0_0.bit0.storage ( storage_2_0_0.bit0.obuf0 A ) ( storage_2_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 427 343 ) ( * 357 ) ++ NEW metal3 ( 332 357 ) ( 427 * ) ++ NEW metal1 ( 427 343 ) via1_4 ++ NEW metal2 ( 427 357 ) via2_5 ++ NEW metal1 ( 332 357 ) via1_4 ++ NEW metal2 ( 332 357 ) via2_5 ; ++ - storage_2_0_0.bit1.d ( storage_2_0_0.bit1.dmux0_inv ZN ) ( storage_2_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 731 343 ) ( 1244 * ) ++ NEW metal1 ( 731 343 ) via1_4 ++ NEW metal2 ( 731 343 ) via2_5 ++ NEW metal1 ( 1244 343 ) via1_4 ++ NEW metal2 ( 1244 343 ) via2_5 ; ++ - storage_2_0_0.bit1.d_pair0_b ( storage_2_0_0.bit1.dmux0_inv A ) ( storage_2_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 343 ) ( * 357 ) ++ NEW metal3 ( 1187 357 ) ( 1225 * ) ++ NEW metal1 ( 1225 343 ) via1_4 ++ NEW metal2 ( 1225 357 ) via2_5 ++ NEW metal1 ( 1187 357 ) via1_7 ++ NEW metal2 ( 1187 357 ) via2_5 ; ++ - storage_2_0_0.bit1.storage ( storage_2_0_0.bit1.obuf0 A ) ( storage_2_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1054 343 ) ( * 357 ) ++ NEW metal3 ( 959 357 ) ( 1054 * ) ++ NEW metal1 ( 1054 343 ) via1_4 ++ NEW metal2 ( 1054 357 ) via2_5 ++ NEW metal1 ( 959 357 ) via1_4 ++ NEW metal2 ( 959 357 ) via2_5 ; ++ - storage_2_0_0.bit2.d ( storage_2_0_0.bit2.dmux0_inv ZN ) ( storage_2_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1358 343 ) ( 1871 * ) ++ NEW metal1 ( 1358 343 ) via1_4 ++ NEW metal2 ( 1358 343 ) via2_5 ++ NEW metal1 ( 1871 343 ) via1_4 ++ NEW metal2 ( 1871 343 ) via2_5 ; ++ - storage_2_0_0.bit2.d_pair0_b ( storage_2_0_0.bit2.dmux0_inv A ) ( storage_2_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 343 ) ( * 357 ) ++ NEW metal3 ( 1814 357 ) ( 1852 * ) ++ NEW metal1 ( 1852 343 ) via1_4 ++ NEW metal2 ( 1852 357 ) via2_5 ++ NEW metal1 ( 1814 357 ) via1_7 ++ NEW metal2 ( 1814 357 ) via2_5 ; ++ - storage_2_0_0.bit2.storage ( storage_2_0_0.bit2.obuf0 A ) ( storage_2_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1681 343 ) ( * 357 ) ++ NEW metal3 ( 1586 357 ) ( 1681 * ) ++ NEW metal1 ( 1681 343 ) via1_4 ++ NEW metal2 ( 1681 357 ) via2_5 ++ NEW metal1 ( 1586 357 ) via1_4 ++ NEW metal2 ( 1586 357 ) via2_5 ; ++ - storage_2_0_0.bit3.d ( storage_2_0_0.bit3.dmux0_inv ZN ) ( storage_2_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1985 343 ) ( 2498 * ) ++ NEW metal1 ( 1985 343 ) via1_4 ++ NEW metal2 ( 1985 343 ) via2_5 ++ NEW metal1 ( 2498 343 ) via1_4 ++ NEW metal2 ( 2498 343 ) via2_5 ; ++ - storage_2_0_0.bit3.d_pair0_b ( storage_2_0_0.bit3.dmux0_inv A ) ( storage_2_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 343 ) ( * 357 ) ++ NEW metal3 ( 2441 357 ) ( 2479 * ) ++ NEW metal1 ( 2479 343 ) via1_4 ++ NEW metal2 ( 2479 357 ) via2_5 ++ NEW metal1 ( 2441 357 ) via1_7 ++ NEW metal2 ( 2441 357 ) via2_5 ; ++ - storage_2_0_0.bit3.storage ( storage_2_0_0.bit3.obuf0 A ) ( storage_2_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 343 ) ( * 357 ) ++ NEW metal3 ( 2213 357 ) ( 2308 * ) ++ NEW metal1 ( 2308 343 ) via1_4 ++ NEW metal2 ( 2308 357 ) via2_5 ++ NEW metal1 ( 2213 357 ) via1_4 ++ NEW metal2 ( 2213 357 ) via2_5 ; ++ - storage_2_0_0.bit4.d ( storage_2_0_0.bit4.dmux0_inv ZN ) ( storage_2_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 2612 343 ) ( 3125 * ) ++ NEW metal1 ( 2612 343 ) via1_4 ++ NEW metal2 ( 2612 343 ) via2_5 ++ NEW metal1 ( 3125 343 ) via1_4 ++ NEW metal2 ( 3125 343 ) via2_5 ; ++ - storage_2_0_0.bit4.d_pair0_b ( storage_2_0_0.bit4.dmux0_inv A ) ( storage_2_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 343 ) ( * 357 ) ++ NEW metal3 ( 3068 357 ) ( 3106 * ) ++ NEW metal1 ( 3106 343 ) via1_4 ++ NEW metal2 ( 3106 357 ) via2_5 ++ NEW metal1 ( 3068 357 ) via1_7 ++ NEW metal2 ( 3068 357 ) via2_5 ; ++ - storage_2_0_0.bit4.storage ( storage_2_0_0.bit4.obuf0 A ) ( storage_2_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 343 ) ( * 357 ) ++ NEW metal3 ( 2840 357 ) ( 2935 * ) ++ NEW metal1 ( 2935 343 ) via1_4 ++ NEW metal2 ( 2935 357 ) via2_5 ++ NEW metal1 ( 2840 357 ) via1_4 ++ NEW metal2 ( 2840 357 ) via2_5 ; ++ - storage_2_0_0.bit5.d ( storage_2_0_0.bit5.dmux0_inv ZN ) ( storage_2_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3239 343 ) ( 3752 * ) ++ NEW metal1 ( 3752 343 ) via1_4 ++ NEW metal2 ( 3752 343 ) via2_5 ++ NEW metal1 ( 3239 343 ) via1_4 ++ NEW metal2 ( 3239 343 ) via2_5 ; ++ - storage_2_0_0.bit5.d_pair0_b ( storage_2_0_0.bit5.dmux0_inv A ) ( storage_2_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 343 ) ( * 357 ) ++ NEW metal3 ( 3695 357 ) ( 3733 * ) ++ NEW metal1 ( 3733 343 ) via1_4 ++ NEW metal2 ( 3733 357 ) via2_5 ++ NEW metal1 ( 3695 357 ) via1_7 ++ NEW metal2 ( 3695 357 ) via2_5 ; ++ - storage_2_0_0.bit5.storage ( storage_2_0_0.bit5.obuf0 A ) ( storage_2_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3562 343 ) ( * 357 ) ++ NEW metal3 ( 3467 357 ) ( 3562 * ) ++ NEW metal1 ( 3562 343 ) via1_4 ++ NEW metal2 ( 3562 357 ) via2_5 ++ NEW metal1 ( 3467 357 ) via1_4 ++ NEW metal2 ( 3467 357 ) via2_5 ; ++ - storage_2_0_0.bit6.d ( storage_2_0_0.bit6.dmux0_inv ZN ) ( storage_2_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3866 343 ) ( 4379 * ) ++ NEW metal1 ( 3866 343 ) via1_4 ++ NEW metal2 ( 3866 343 ) via2_5 ++ NEW metal1 ( 4379 343 ) via1_4 ++ NEW metal2 ( 4379 343 ) via2_5 ; ++ - storage_2_0_0.bit6.d_pair0_b ( storage_2_0_0.bit6.dmux0_inv A ) ( storage_2_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 343 ) ( * 357 ) ++ NEW metal3 ( 4322 357 ) ( 4360 * ) ++ NEW metal1 ( 4360 343 ) via1_4 ++ NEW metal2 ( 4360 357 ) via2_5 ++ NEW metal1 ( 4322 357 ) via1_7 ++ NEW metal2 ( 4322 357 ) via2_5 ; ++ - storage_2_0_0.bit6.storage ( storage_2_0_0.bit6.obuf0 A ) ( storage_2_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4189 343 ) ( * 357 ) ++ NEW metal3 ( 4094 357 ) ( 4189 * ) ++ NEW metal1 ( 4189 343 ) via1_4 ++ NEW metal2 ( 4189 357 ) via2_5 ++ NEW metal1 ( 4094 357 ) via1_4 ++ NEW metal2 ( 4094 357 ) via2_5 ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCK ) ( storage_2_0_0.bit6.bit CK ) ( storage_2_0_0.bit5.bit CK ) ( storage_2_0_0.bit4.bit CK ) ( storage_2_0_0.bit3.bit CK ) ( storage_2_0_0.bit2.bit CK ) ( storage_2_0_0.bit1.bit CK ) ++ ( storage_2_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 301 ) ( * 343 ) ++ NEW metal2 ( 180 301 ) ( * 343 ) ++ NEW metal3 ( 180 301 ) ( 807 * ) ++ NEW metal2 ( 3942 329 ) ( * 343 ) ++ NEW metal2 ( 3942 301 ) ( * 329 ) ++ NEW metal2 ( 3315 301 ) ( * 343 ) ++ NEW metal2 ( 2688 301 ) ( * 343 ) ++ NEW metal3 ( 2688 301 ) ( 3315 * ) ++ NEW metal2 ( 2061 301 ) ( * 343 ) ++ NEW metal3 ( 2061 301 ) ( 2688 * ) ++ NEW metal2 ( 1434 301 ) ( * 343 ) ++ NEW metal3 ( 1434 301 ) ( 2061 * ) ++ NEW metal3 ( 807 301 ) ( 1434 * ) ++ NEW metal3 ( 3315 301 ) ( 3942 * ) ++ NEW metal3 ( 3942 329 ) ( 4987 * ) ++ NEW metal1 ( 807 343 ) via1_4 ++ NEW metal2 ( 807 301 ) via2_5 ++ NEW metal1 ( 180 343 ) via1_4 ++ NEW metal2 ( 180 301 ) via2_5 ++ NEW metal1 ( 3942 343 ) via1_4 ++ NEW metal2 ( 3942 329 ) via2_5 ++ NEW metal2 ( 3942 301 ) via2_5 ++ NEW metal1 ( 3315 343 ) via1_4 ++ NEW metal2 ( 3315 301 ) via2_5 ++ NEW metal1 ( 2688 343 ) via1_4 ++ NEW metal2 ( 2688 301 ) via2_5 ++ NEW metal1 ( 2061 343 ) via1_4 ++ NEW metal2 ( 2061 301 ) via2_5 ++ NEW metal1 ( 1434 343 ) via1_4 ++ NEW metal2 ( 1434 301 ) via2_5 ++ NEW metal1 ( 4987 329 ) via1_4 ++ NEW metal2 ( 4987 329 ) via2_5 ; ++ - storage_2_0_0.later0_b ( storage_2_0_0.take_and0 A2 ) ( storage_2_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 343 ) ( * 371 ) ++ NEW metal2 ( 4588 371 ) ( 4626 * ) ++ NEW metal1 ( 4626 343 ) via1_4 ++ NEW metal1 ( 4588 371 ) via1_4 ; ++ - storage_2_0_0.select0_b ( storage_2_0_0.select_inv_0 ZN ) ( storage_2_0_0.bit6.obuf0 EN ) ( storage_2_0_0.bit5.obuf0 EN ) ( storage_2_0_0.bit4.obuf0 EN ) ( storage_2_0_0.bit3.obuf0 EN ) ( storage_2_0_0.bit2.obuf0 EN ) ( storage_2_0_0.bit1.obuf0 EN ) ++ ( storage_2_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal3 ( 465 371 ) ( 1092 * ) ++ NEW metal3 ( 3600 371 ) ( 4227 * ) ++ NEW metal3 ( 2346 371 ) ( 2973 * ) ++ NEW metal3 ( 1719 371 ) ( 2346 * ) ++ NEW metal3 ( 1092 371 ) ( 1719 * ) ++ NEW metal3 ( 2973 371 ) ( 3600 * ) ++ NEW metal3 ( 4227 371 ) ( 5025 * ) ++ NEW metal1 ( 1092 371 ) via1_4 ++ NEW metal2 ( 1092 371 ) via2_5 ++ NEW metal1 ( 465 371 ) via1_4 ++ NEW metal2 ( 465 371 ) via2_5 ++ NEW metal1 ( 4227 371 ) via1_4 ++ NEW metal2 ( 4227 371 ) via2_5 ++ NEW metal1 ( 3600 371 ) via1_4 ++ NEW metal2 ( 3600 371 ) via2_5 ++ NEW metal1 ( 2973 371 ) via1_4 ++ NEW metal2 ( 2973 371 ) via2_5 ++ NEW metal1 ( 2346 371 ) via1_4 ++ NEW metal2 ( 2346 371 ) via2_5 ++ NEW metal1 ( 1719 371 ) via1_4 ++ NEW metal2 ( 1719 371 ) via2_5 ++ NEW metal1 ( 5025 371 ) via1_4 ++ NEW metal2 ( 5025 371 ) via2_5 ; ++ - storage_2_0_0.take0 ( storage_2_0_0.bit6.dmux0 A1 ) ( storage_2_0_0.bit5.dmux0 A1 ) ( storage_2_0_0.bit4.dmux0 A1 ) ( storage_2_0_0.bit3.dmux0 A1 ) ( storage_2_0_0.bit2.dmux0 A1 ) ( storage_2_0_0.bit1.dmux0 A1 ) ( storage_2_0_0.bit0.dmux0 A1 ) ++ ( storage_2_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 560 329 ) ( 1187 * ) ++ NEW metal2 ( 4322 315 ) ( * 329 ) ++ NEW metal2 ( 3695 315 ) ( * 329 ) ++ NEW metal3 ( 3695 315 ) ( 4322 * ) ++ NEW metal3 ( 3420 315 ) ( 3695 * ) ++ NEW metal3 ( 1814 329 ) ( 2441 * ) ++ NEW metal3 ( 2441 329 ) ( 3068 * ) ++ NEW metal3 ( 3420 315 ) ( * 329 ) ++ NEW metal3 ( 3068 329 ) ( 3420 * ) ++ NEW metal3 ( 1187 329 ) ( 1814 * ) ++ NEW metal3 ( 4322 315 ) ( 4664 * ) ++ NEW metal1 ( 1187 329 ) via1_4 ++ NEW metal2 ( 1187 329 ) via2_5 ++ NEW metal1 ( 560 329 ) via1_4 ++ NEW metal2 ( 560 329 ) via2_5 ++ NEW metal1 ( 4322 329 ) via1_4 ++ NEW metal2 ( 4322 315 ) via2_5 ++ NEW metal1 ( 3695 329 ) via1_4 ++ NEW metal2 ( 3695 315 ) via2_5 ++ NEW metal1 ( 1814 329 ) via1_4 ++ NEW metal2 ( 1814 329 ) via2_5 ++ NEW metal1 ( 2441 329 ) via1_4 ++ NEW metal2 ( 2441 329 ) via2_5 ++ NEW metal1 ( 3068 329 ) via1_4 ++ NEW metal2 ( 3068 329 ) via2_5 ++ NEW metal1 ( 4664 315 ) via1_4 ++ NEW metal2 ( 4664 315 ) via2_5 ; ++ - storage_2_0_0.we ( storage_2_0_0.cg E ) ( storage_2_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 343 ) ( 4854 * ) ++ NEW metal1 ( 4854 343 ) via1_4 ++ NEW metal2 ( 4854 343 ) via2_5 ++ NEW metal1 ( 4740 343 ) via1_4 ++ NEW metal2 ( 4740 343 ) via2_5 ; ++ - storage_2_0_0.we0 ( storage_2_0_0.any_or0 A2 ) ( storage_2_0_0.take_and0 A1 ) ( storage_2_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 343 ) ( 4702 * ) ++ NEW metal3 ( 4474 343 ) ( 4607 * ) ++ NEW metal1 ( 4474 343 ) via1_4 ++ NEW metal2 ( 4474 343 ) via2_5 ++ NEW metal1 ( 4607 343 ) via1_4 ++ NEW metal2 ( 4607 343 ) via2_5 ++ NEW metal1 ( 4702 343 ) via1_4 ++ NEW metal2 ( 4702 343 ) via2_5 ; ++ - storage_2_0_0.we1 ( storage_2_0_0.bit6.dmux0 B1 ) ( storage_2_0_0.bit5.dmux0 B1 ) ( storage_2_0_0.bit4.dmux0 B1 ) ( storage_2_0_0.bit3.dmux0 B1 ) ( storage_2_0_0.bit2.dmux0 B1 ) ( storage_2_0_0.bit1.dmux0 B1 ) ( storage_2_0_0.bit0.dmux0 B1 ) ++ ( storage_2_0_0.any_or0 A1 ) ( storage_2_0_0.later_inv0 A ) ( storage_2_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 315 ) ( * 343 ) ++ NEW metal3 ( 522 315 ) ( 1149 * ) ++ NEW metal2 ( 522 315 ) ( * 343 ) ++ NEW metal2 ( 3657 343 ) ( * 399 ) ++ NEW metal2 ( 4284 343 ) ( * 399 ) ++ NEW metal3 ( 3657 399 ) ( 4284 * ) ++ NEW metal3 ( 4284 399 ) ( 4550 * ) ++ NEW metal2 ( 3030 343 ) ( * 399 ) ++ NEW metal2 ( 2403 343 ) ( * 399 ) ++ NEW metal3 ( 2403 399 ) ( 3030 * ) ++ NEW metal2 ( 1776 343 ) ( * 399 ) ++ NEW metal3 ( 1776 399 ) ( 2403 * ) ++ NEW metal2 ( 1776 315 ) ( * 343 ) ++ NEW metal3 ( 1149 315 ) ( 1776 * ) ++ NEW metal3 ( 3030 399 ) ( 3657 * ) ++ NEW metal2 ( 4569 343 ) ( * 399 ) ++ NEW metal2 ( 4683 343 ) ( * 357 ) ++ NEW metal3 ( 4569 357 ) ( 4683 * ) ++ NEW metal2 ( 4550 399 ) ( 4569 * ) ++ NEW metal1 ( 1149 343 ) via1_4 ++ NEW metal2 ( 1149 315 ) via2_5 ++ NEW metal2 ( 522 315 ) via2_5 ++ NEW metal1 ( 522 343 ) via1_4 ++ NEW metal1 ( 3657 343 ) via1_4 ++ NEW metal2 ( 3657 399 ) via2_5 ++ NEW metal1 ( 4284 343 ) via1_4 ++ NEW metal2 ( 4284 399 ) via2_5 ++ NEW metal1 ( 4550 399 ) via1_7 ++ NEW metal2 ( 4550 399 ) via2_5 ++ NEW metal1 ( 3030 343 ) via1_4 ++ NEW metal2 ( 3030 399 ) via2_5 ++ NEW metal1 ( 2403 343 ) via1_4 ++ NEW metal2 ( 2403 399 ) via2_5 ++ NEW metal1 ( 1776 343 ) via1_4 ++ NEW metal2 ( 1776 399 ) via2_5 ++ NEW metal2 ( 1776 315 ) via2_5 ++ NEW metal1 ( 4569 343 ) via1_4 ++ NEW metal1 ( 4683 343 ) via1_4 ++ NEW metal2 ( 4683 357 ) via2_5 ++ NEW metal2 ( 4569 357 ) via2_5 ; ++ - storage_3_0_0.bit0.d ( storage_3_0_0.bit0.dmux0_inv ZN ) ( storage_3_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 104 497 ) ( 617 * ) ++ NEW metal1 ( 104 497 ) via1_4 ++ NEW metal2 ( 104 497 ) via2_5 ++ NEW metal1 ( 617 497 ) via1_4 ++ NEW metal2 ( 617 497 ) via2_5 ; ++ - storage_3_0_0.bit0.d_pair0_b ( storage_3_0_0.bit0.dmux0_inv A ) ( storage_3_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 483 ) ( * 497 ) ++ NEW metal3 ( 560 483 ) ( 598 * ) ++ NEW metal1 ( 598 497 ) via1_4 ++ NEW metal2 ( 598 483 ) via2_5 ++ NEW metal1 ( 560 483 ) via1_7 ++ NEW metal2 ( 560 483 ) via2_5 ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.obuf0 A ) ( storage_3_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 427 497 ) ( * 511 ) ++ NEW metal3 ( 332 511 ) ( 427 * ) ++ NEW metal1 ( 427 497 ) via1_4 ++ NEW metal2 ( 427 511 ) via2_5 ++ NEW metal1 ( 332 511 ) via1_4 ++ NEW metal2 ( 332 511 ) via2_5 ; ++ - storage_3_0_0.bit1.d ( storage_3_0_0.bit1.dmux0_inv ZN ) ( storage_3_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 731 497 ) ( 1244 * ) ++ NEW metal1 ( 731 497 ) via1_4 ++ NEW metal2 ( 731 497 ) via2_5 ++ NEW metal1 ( 1244 497 ) via1_4 ++ NEW metal2 ( 1244 497 ) via2_5 ; ++ - storage_3_0_0.bit1.d_pair0_b ( storage_3_0_0.bit1.dmux0_inv A ) ( storage_3_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 483 ) ( * 497 ) ++ NEW metal3 ( 1187 483 ) ( 1225 * ) ++ NEW metal1 ( 1225 497 ) via1_4 ++ NEW metal2 ( 1225 483 ) via2_5 ++ NEW metal1 ( 1187 483 ) via1_7 ++ NEW metal2 ( 1187 483 ) via2_5 ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.obuf0 A ) ( storage_3_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1054 497 ) ( * 511 ) ++ NEW metal3 ( 959 511 ) ( 1054 * ) ++ NEW metal1 ( 1054 497 ) via1_4 ++ NEW metal2 ( 1054 511 ) via2_5 ++ NEW metal1 ( 959 511 ) via1_4 ++ NEW metal2 ( 959 511 ) via2_5 ; ++ - storage_3_0_0.bit2.d ( storage_3_0_0.bit2.dmux0_inv ZN ) ( storage_3_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1358 497 ) ( 1871 * ) ++ NEW metal1 ( 1358 497 ) via1_4 ++ NEW metal2 ( 1358 497 ) via2_5 ++ NEW metal1 ( 1871 497 ) via1_4 ++ NEW metal2 ( 1871 497 ) via2_5 ; ++ - storage_3_0_0.bit2.d_pair0_b ( storage_3_0_0.bit2.dmux0_inv A ) ( storage_3_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 483 ) ( * 497 ) ++ NEW metal3 ( 1814 483 ) ( 1852 * ) ++ NEW metal1 ( 1852 497 ) via1_4 ++ NEW metal2 ( 1852 483 ) via2_5 ++ NEW metal1 ( 1814 483 ) via1_7 ++ NEW metal2 ( 1814 483 ) via2_5 ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.obuf0 A ) ( storage_3_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1681 497 ) ( * 511 ) ++ NEW metal3 ( 1586 511 ) ( 1681 * ) ++ NEW metal1 ( 1681 497 ) via1_4 ++ NEW metal2 ( 1681 511 ) via2_5 ++ NEW metal1 ( 1586 511 ) via1_4 ++ NEW metal2 ( 1586 511 ) via2_5 ; ++ - storage_3_0_0.bit3.d ( storage_3_0_0.bit3.dmux0_inv ZN ) ( storage_3_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1985 497 ) ( 2498 * ) ++ NEW metal1 ( 1985 497 ) via1_4 ++ NEW metal2 ( 1985 497 ) via2_5 ++ NEW metal1 ( 2498 497 ) via1_4 ++ NEW metal2 ( 2498 497 ) via2_5 ; ++ - storage_3_0_0.bit3.d_pair0_b ( storage_3_0_0.bit3.dmux0_inv A ) ( storage_3_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 483 ) ( * 497 ) ++ NEW metal3 ( 2441 483 ) ( 2479 * ) ++ NEW metal1 ( 2479 497 ) via1_4 ++ NEW metal2 ( 2479 483 ) via2_5 ++ NEW metal1 ( 2441 483 ) via1_7 ++ NEW metal2 ( 2441 483 ) via2_5 ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.obuf0 A ) ( storage_3_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 497 ) ( * 511 ) ++ NEW metal3 ( 2213 511 ) ( 2308 * ) ++ NEW metal1 ( 2308 497 ) via1_4 ++ NEW metal2 ( 2308 511 ) via2_5 ++ NEW metal1 ( 2213 511 ) via1_4 ++ NEW metal2 ( 2213 511 ) via2_5 ; ++ - storage_3_0_0.bit4.d ( storage_3_0_0.bit4.dmux0_inv ZN ) ( storage_3_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 2612 497 ) ( 3125 * ) ++ NEW metal1 ( 2612 497 ) via1_4 ++ NEW metal2 ( 2612 497 ) via2_5 ++ NEW metal1 ( 3125 497 ) via1_4 ++ NEW metal2 ( 3125 497 ) via2_5 ; ++ - storage_3_0_0.bit4.d_pair0_b ( storage_3_0_0.bit4.dmux0_inv A ) ( storage_3_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 483 ) ( * 497 ) ++ NEW metal3 ( 3068 483 ) ( 3106 * ) ++ NEW metal1 ( 3106 497 ) via1_4 ++ NEW metal2 ( 3106 483 ) via2_5 ++ NEW metal1 ( 3068 483 ) via1_7 ++ NEW metal2 ( 3068 483 ) via2_5 ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.obuf0 A ) ( storage_3_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 497 ) ( * 511 ) ++ NEW metal3 ( 2840 511 ) ( 2935 * ) ++ NEW metal1 ( 2935 497 ) via1_4 ++ NEW metal2 ( 2935 511 ) via2_5 ++ NEW metal1 ( 2840 511 ) via1_4 ++ NEW metal2 ( 2840 511 ) via2_5 ; ++ - storage_3_0_0.bit5.d ( storage_3_0_0.bit5.dmux0_inv ZN ) ( storage_3_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3239 497 ) ( 3752 * ) ++ NEW metal1 ( 3752 497 ) via1_4 ++ NEW metal2 ( 3752 497 ) via2_5 ++ NEW metal1 ( 3239 497 ) via1_4 ++ NEW metal2 ( 3239 497 ) via2_5 ; ++ - storage_3_0_0.bit5.d_pair0_b ( storage_3_0_0.bit5.dmux0_inv A ) ( storage_3_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 483 ) ( * 497 ) ++ NEW metal3 ( 3695 483 ) ( 3733 * ) ++ NEW metal1 ( 3733 497 ) via1_4 ++ NEW metal2 ( 3733 483 ) via2_5 ++ NEW metal1 ( 3695 483 ) via1_7 ++ NEW metal2 ( 3695 483 ) via2_5 ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.obuf0 A ) ( storage_3_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3562 497 ) ( * 511 ) ++ NEW metal3 ( 3467 511 ) ( 3562 * ) ++ NEW metal1 ( 3562 497 ) via1_4 ++ NEW metal2 ( 3562 511 ) via2_5 ++ NEW metal1 ( 3467 511 ) via1_4 ++ NEW metal2 ( 3467 511 ) via2_5 ; ++ - storage_3_0_0.bit6.d ( storage_3_0_0.bit6.dmux0_inv ZN ) ( storage_3_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3866 497 ) ( 4379 * ) ++ NEW metal1 ( 3866 497 ) via1_4 ++ NEW metal2 ( 3866 497 ) via2_5 ++ NEW metal1 ( 4379 497 ) via1_4 ++ NEW metal2 ( 4379 497 ) via2_5 ; ++ - storage_3_0_0.bit6.d_pair0_b ( storage_3_0_0.bit6.dmux0_inv A ) ( storage_3_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 483 ) ( * 497 ) ++ NEW metal3 ( 4322 483 ) ( 4360 * ) ++ NEW metal1 ( 4360 497 ) via1_4 ++ NEW metal2 ( 4360 483 ) via2_5 ++ NEW metal1 ( 4322 483 ) via1_7 ++ NEW metal2 ( 4322 483 ) via2_5 ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.obuf0 A ) ( storage_3_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4189 497 ) ( * 511 ) ++ NEW metal3 ( 4094 511 ) ( 4189 * ) ++ NEW metal1 ( 4189 497 ) via1_4 ++ NEW metal2 ( 4189 511 ) via2_5 ++ NEW metal1 ( 4094 511 ) via1_4 ++ NEW metal2 ( 4094 511 ) via2_5 ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCK ) ( storage_3_0_0.bit6.bit CK ) ( storage_3_0_0.bit5.bit CK ) ( storage_3_0_0.bit4.bit CK ) ( storage_3_0_0.bit3.bit CK ) ( storage_3_0_0.bit2.bit CK ) ( storage_3_0_0.bit1.bit CK ) ++ ( storage_3_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 455 ) ( * 497 ) ++ NEW metal2 ( 180 455 ) ( * 497 ) ++ NEW metal3 ( 180 455 ) ( 807 * ) ++ NEW metal2 ( 3942 497 ) ( * 525 ) ++ NEW metal2 ( 3942 455 ) ( * 497 ) ++ NEW metal2 ( 3315 455 ) ( * 497 ) ++ NEW metal2 ( 2688 455 ) ( * 497 ) ++ NEW metal3 ( 2688 455 ) ( 3315 * ) ++ NEW metal2 ( 2061 455 ) ( * 497 ) ++ NEW metal3 ( 2061 455 ) ( 2688 * ) ++ NEW metal2 ( 1434 455 ) ( * 497 ) ++ NEW metal3 ( 1434 455 ) ( 2061 * ) ++ NEW metal3 ( 807 455 ) ( 1434 * ) ++ NEW metal3 ( 3315 455 ) ( 3942 * ) ++ NEW metal3 ( 3942 525 ) ( 4987 * ) ++ NEW metal1 ( 807 497 ) via1_4 ++ NEW metal2 ( 807 455 ) via2_5 ++ NEW metal1 ( 180 497 ) via1_4 ++ NEW metal2 ( 180 455 ) via2_5 ++ NEW metal1 ( 3942 497 ) via1_4 ++ NEW metal2 ( 3942 525 ) via2_5 ++ NEW metal2 ( 3942 455 ) via2_5 ++ NEW metal1 ( 3315 497 ) via1_4 ++ NEW metal2 ( 3315 455 ) via2_5 ++ NEW metal1 ( 2688 497 ) via1_4 ++ NEW metal2 ( 2688 455 ) via2_5 ++ NEW metal1 ( 2061 497 ) via1_4 ++ NEW metal2 ( 2061 455 ) via2_5 ++ NEW metal1 ( 1434 497 ) via1_4 ++ NEW metal2 ( 1434 455 ) via2_5 ++ NEW metal1 ( 4987 525 ) via1_4 ++ NEW metal2 ( 4987 525 ) via2_5 ; ++ - storage_3_0_0.later0_b ( storage_3_0_0.take_and0 A2 ) ( storage_3_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 497 ) ( * 525 ) ++ NEW metal2 ( 4588 525 ) ( 4626 * ) ++ NEW metal1 ( 4626 497 ) via1_4 ++ NEW metal1 ( 4588 525 ) via1_4 ; ++ - storage_3_0_0.select0_b ( storage_3_0_0.select_inv_0 ZN ) ( storage_3_0_0.bit6.obuf0 EN ) ( storage_3_0_0.bit5.obuf0 EN ) ( storage_3_0_0.bit4.obuf0 EN ) ( storage_3_0_0.bit3.obuf0 EN ) ( storage_3_0_0.bit2.obuf0 EN ) ( storage_3_0_0.bit1.obuf0 EN ) ++ ( storage_3_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal3 ( 465 469 ) ( 1092 * ) ++ NEW metal3 ( 3600 469 ) ( 4227 * ) ++ NEW metal2 ( 3600 441 ) ( * 469 ) ++ NEW metal2 ( 2973 441 ) ( * 469 ) ++ NEW metal2 ( 2346 441 ) ( * 469 ) ++ NEW metal3 ( 2346 441 ) ( 2973 * ) ++ NEW metal2 ( 1719 441 ) ( * 469 ) ++ NEW metal3 ( 1719 441 ) ( 2346 * ) ++ NEW metal3 ( 1092 469 ) ( 1719 * ) ++ NEW metal3 ( 2973 441 ) ( 3600 * ) ++ NEW metal3 ( 4227 469 ) ( 5025 * ) ++ NEW metal1 ( 1092 469 ) via1_4 ++ NEW metal2 ( 1092 469 ) via2_5 ++ NEW metal1 ( 465 469 ) via1_4 ++ NEW metal2 ( 465 469 ) via2_5 ++ NEW metal1 ( 4227 469 ) via1_4 ++ NEW metal2 ( 4227 469 ) via2_5 ++ NEW metal1 ( 3600 469 ) via1_4 ++ NEW metal2 ( 3600 469 ) via2_5 ++ NEW metal2 ( 3600 441 ) via2_5 ++ NEW metal1 ( 2973 469 ) via1_4 ++ NEW metal2 ( 2973 441 ) via2_5 ++ NEW metal1 ( 2346 469 ) via1_4 ++ NEW metal2 ( 2346 441 ) via2_5 ++ NEW metal1 ( 1719 469 ) via1_4 ++ NEW metal2 ( 1719 441 ) via2_5 ++ NEW metal2 ( 1719 469 ) via2_5 ++ NEW metal1 ( 5025 469 ) via1_4 ++ NEW metal2 ( 5025 469 ) via2_5 ; ++ - storage_3_0_0.take0 ( storage_3_0_0.bit6.dmux0 A1 ) ( storage_3_0_0.bit5.dmux0 A1 ) ( storage_3_0_0.bit4.dmux0 A1 ) ( storage_3_0_0.bit3.dmux0 A1 ) ( storage_3_0_0.bit2.dmux0 A1 ) ( storage_3_0_0.bit1.dmux0 A1 ) ( storage_3_0_0.bit0.dmux0 A1 ) ++ ( storage_3_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1187 511 ) ( * 525 ) ++ NEW metal3 ( 560 525 ) ( 1187 * ) ++ NEW metal2 ( 560 511 ) ( * 525 ) ++ NEW metal2 ( 3695 511 ) ( * 525 ) ++ NEW metal2 ( 4322 511 ) ( * 539 ) ++ NEW metal3 ( 3901 539 ) ( 4322 * ) ++ NEW metal3 ( 3901 525 ) ( * 539 ) ++ NEW metal3 ( 3695 525 ) ( 3901 * ) ++ NEW metal2 ( 1814 511 ) ( * 525 ) ++ NEW metal2 ( 2441 511 ) ( * 525 ) ++ NEW metal3 ( 1814 525 ) ( 2441 * ) ++ NEW metal2 ( 3068 511 ) ( * 525 ) ++ NEW metal3 ( 2441 525 ) ( 3068 * ) ++ NEW metal3 ( 1187 525 ) ( 1814 * ) ++ NEW metal3 ( 3068 525 ) ( 3695 * ) ++ NEW metal3 ( 4322 539 ) ( 4664 * ) ++ NEW metal1 ( 1187 511 ) via1_4 ++ NEW metal2 ( 1187 525 ) via2_5 ++ NEW metal2 ( 560 525 ) via2_5 ++ NEW metal1 ( 560 511 ) via1_4 ++ NEW metal1 ( 3695 511 ) via1_4 ++ NEW metal2 ( 3695 525 ) via2_5 ++ NEW metal1 ( 4322 511 ) via1_4 ++ NEW metal2 ( 4322 539 ) via2_5 ++ NEW metal1 ( 1814 511 ) via1_4 ++ NEW metal2 ( 1814 525 ) via2_5 ++ NEW metal1 ( 2441 511 ) via1_4 ++ NEW metal2 ( 2441 525 ) via2_5 ++ NEW metal1 ( 3068 511 ) via1_4 ++ NEW metal2 ( 3068 525 ) via2_5 ++ NEW metal1 ( 4664 539 ) via1_7 ++ NEW metal2 ( 4664 539 ) via2_5 ; ++ - storage_3_0_0.we ( storage_3_0_0.cg E ) ( storage_3_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 497 ) ( 4854 * ) ++ NEW metal1 ( 4854 497 ) via1_4 ++ NEW metal2 ( 4854 497 ) via2_5 ++ NEW metal1 ( 4740 497 ) via1_4 ++ NEW metal2 ( 4740 497 ) via2_5 ; ++ - storage_3_0_0.we0 ( storage_3_0_0.any_or0 A2 ) ( storage_3_0_0.take_and0 A1 ) ( storage_3_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 497 ) ( 4702 * ) ++ NEW metal3 ( 4474 497 ) ( 4607 * ) ++ NEW metal1 ( 4474 497 ) via1_4 ++ NEW metal2 ( 4474 497 ) via2_5 ++ NEW metal1 ( 4607 497 ) via1_4 ++ NEW metal2 ( 4607 497 ) via2_5 ++ NEW metal1 ( 4702 497 ) via1_4 ++ NEW metal2 ( 4702 497 ) via2_5 ; ++ - storage_3_0_0.we1 ( storage_3_0_0.bit6.dmux0 B1 ) ( storage_3_0_0.bit5.dmux0 B1 ) ( storage_3_0_0.bit4.dmux0 B1 ) ( storage_3_0_0.bit3.dmux0 B1 ) ( storage_3_0_0.bit2.dmux0 B1 ) ( storage_3_0_0.bit1.dmux0 B1 ) ( storage_3_0_0.bit0.dmux0 B1 ) ++ ( storage_3_0_0.any_or0 A1 ) ( storage_3_0_0.later_inv0 A ) ( storage_3_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 497 ) ( * 539 ) ++ NEW metal3 ( 522 539 ) ( 1149 * ) ++ NEW metal2 ( 522 497 ) ( * 539 ) ++ NEW metal2 ( 3657 497 ) ( * 539 ) ++ NEW metal2 ( 4284 497 ) ( * 553 ) ++ NEW metal3 ( 3873 553 ) ( 4284 * ) ++ NEW metal3 ( 3873 539 ) ( * 553 ) ++ NEW metal3 ( 3657 539 ) ( 3873 * ) ++ NEW metal3 ( 4284 511 ) ( 4550 * ) ++ NEW metal2 ( 3030 497 ) ( * 539 ) ++ NEW metal2 ( 2403 497 ) ( * 539 ) ++ NEW metal3 ( 2403 539 ) ( 3030 * ) ++ NEW metal2 ( 1776 497 ) ( * 539 ) ++ NEW metal3 ( 1776 539 ) ( 2403 * ) ++ NEW metal3 ( 1149 539 ) ( 1776 * ) ++ NEW metal3 ( 3030 539 ) ( 3657 * ) ++ NEW metal2 ( 4569 497 ) ( * 511 ) ++ NEW metal2 ( 4683 497 ) ( * 511 ) ++ NEW metal2 ( 4550 511 ) ( 4569 * ) ++ NEW metal3 ( 4550 511 ) ( 4683 * ) ++ NEW metal1 ( 1149 497 ) via1_4 ++ NEW metal2 ( 1149 539 ) via2_5 ++ NEW metal2 ( 522 539 ) via2_5 ++ NEW metal1 ( 522 497 ) via1_4 ++ NEW metal1 ( 3657 497 ) via1_4 ++ NEW metal2 ( 3657 539 ) via2_5 ++ NEW metal1 ( 4284 497 ) via1_4 ++ NEW metal2 ( 4284 553 ) via2_5 ++ NEW metal1 ( 4550 511 ) via1_4 ++ NEW metal2 ( 4550 511 ) via2_5 ++ NEW metal2 ( 4284 511 ) via2_5 ++ NEW metal1 ( 3030 497 ) via1_4 ++ NEW metal2 ( 3030 539 ) via2_5 ++ NEW metal1 ( 2403 497 ) via1_4 ++ NEW metal2 ( 2403 539 ) via2_5 ++ NEW metal1 ( 1776 497 ) via1_4 ++ NEW metal2 ( 1776 539 ) via2_5 ++ NEW metal1 ( 4569 497 ) via1_4 ++ NEW metal2 ( 4683 511 ) via2_5 ++ NEW metal1 ( 4683 497 ) via1_4 ; ++ - storage_4_0_0.bit0.d ( storage_4_0_0.bit0.dmux0_inv ZN ) ( storage_4_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 104 623 ) ( 617 * ) ++ NEW metal1 ( 104 623 ) via1_4 ++ NEW metal2 ( 104 623 ) via2_5 ++ NEW metal1 ( 617 623 ) via1_4 ++ NEW metal2 ( 617 623 ) via2_5 ; ++ - storage_4_0_0.bit0.d_pair0_b ( storage_4_0_0.bit0.dmux0_inv A ) ( storage_4_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 623 ) ( * 637 ) ++ NEW metal3 ( 560 637 ) ( 598 * ) ++ NEW metal1 ( 598 623 ) via1_4 ++ NEW metal2 ( 598 637 ) via2_5 ++ NEW metal1 ( 560 637 ) via1_7 ++ NEW metal2 ( 560 637 ) via2_5 ; ++ - storage_4_0_0.bit0.storage ( storage_4_0_0.bit0.obuf0 A ) ( storage_4_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 427 623 ) ( * 637 ) ++ NEW metal3 ( 332 637 ) ( 427 * ) ++ NEW metal1 ( 427 623 ) via1_4 ++ NEW metal2 ( 427 637 ) via2_5 ++ NEW metal1 ( 332 637 ) via1_4 ++ NEW metal2 ( 332 637 ) via2_5 ; ++ - storage_4_0_0.bit1.d ( storage_4_0_0.bit1.dmux0_inv ZN ) ( storage_4_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 731 623 ) ( 1244 * ) ++ NEW metal1 ( 731 623 ) via1_4 ++ NEW metal2 ( 731 623 ) via2_5 ++ NEW metal1 ( 1244 623 ) via1_4 ++ NEW metal2 ( 1244 623 ) via2_5 ; ++ - storage_4_0_0.bit1.d_pair0_b ( storage_4_0_0.bit1.dmux0_inv A ) ( storage_4_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 623 ) ( * 637 ) ++ NEW metal3 ( 1187 637 ) ( 1225 * ) ++ NEW metal1 ( 1225 623 ) via1_4 ++ NEW metal2 ( 1225 637 ) via2_5 ++ NEW metal1 ( 1187 637 ) via1_7 ++ NEW metal2 ( 1187 637 ) via2_5 ; ++ - storage_4_0_0.bit1.storage ( storage_4_0_0.bit1.obuf0 A ) ( storage_4_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1054 623 ) ( * 637 ) ++ NEW metal3 ( 959 637 ) ( 1054 * ) ++ NEW metal1 ( 1054 623 ) via1_4 ++ NEW metal2 ( 1054 637 ) via2_5 ++ NEW metal1 ( 959 637 ) via1_4 ++ NEW metal2 ( 959 637 ) via2_5 ; ++ - storage_4_0_0.bit2.d ( storage_4_0_0.bit2.dmux0_inv ZN ) ( storage_4_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1358 623 ) ( 1871 * ) ++ NEW metal1 ( 1358 623 ) via1_4 ++ NEW metal2 ( 1358 623 ) via2_5 ++ NEW metal1 ( 1871 623 ) via1_4 ++ NEW metal2 ( 1871 623 ) via2_5 ; ++ - storage_4_0_0.bit2.d_pair0_b ( storage_4_0_0.bit2.dmux0_inv A ) ( storage_4_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 623 ) ( * 637 ) ++ NEW metal3 ( 1814 637 ) ( 1852 * ) ++ NEW metal1 ( 1852 623 ) via1_4 ++ NEW metal2 ( 1852 637 ) via2_5 ++ NEW metal1 ( 1814 637 ) via1_7 ++ NEW metal2 ( 1814 637 ) via2_5 ; ++ - storage_4_0_0.bit2.storage ( storage_4_0_0.bit2.obuf0 A ) ( storage_4_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1681 623 ) ( * 637 ) ++ NEW metal3 ( 1586 637 ) ( 1681 * ) ++ NEW metal1 ( 1681 623 ) via1_4 ++ NEW metal2 ( 1681 637 ) via2_5 ++ NEW metal1 ( 1586 637 ) via1_4 ++ NEW metal2 ( 1586 637 ) via2_5 ; ++ - storage_4_0_0.bit3.d ( storage_4_0_0.bit3.dmux0_inv ZN ) ( storage_4_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1985 623 ) ( 2498 * ) ++ NEW metal1 ( 1985 623 ) via1_4 ++ NEW metal2 ( 1985 623 ) via2_5 ++ NEW metal1 ( 2498 623 ) via1_4 ++ NEW metal2 ( 2498 623 ) via2_5 ; ++ - storage_4_0_0.bit3.d_pair0_b ( storage_4_0_0.bit3.dmux0_inv A ) ( storage_4_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 623 ) ( * 637 ) ++ NEW metal3 ( 2441 637 ) ( 2479 * ) ++ NEW metal1 ( 2479 623 ) via1_4 ++ NEW metal2 ( 2479 637 ) via2_5 ++ NEW metal1 ( 2441 637 ) via1_7 ++ NEW metal2 ( 2441 637 ) via2_5 ; ++ - storage_4_0_0.bit3.storage ( storage_4_0_0.bit3.obuf0 A ) ( storage_4_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 623 ) ( * 637 ) ++ NEW metal3 ( 2213 637 ) ( 2308 * ) ++ NEW metal1 ( 2308 623 ) via1_4 ++ NEW metal2 ( 2308 637 ) via2_5 ++ NEW metal1 ( 2213 637 ) via1_4 ++ NEW metal2 ( 2213 637 ) via2_5 ; ++ - storage_4_0_0.bit4.d ( storage_4_0_0.bit4.dmux0_inv ZN ) ( storage_4_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 2612 623 ) ( 3125 * ) ++ NEW metal1 ( 2612 623 ) via1_4 ++ NEW metal2 ( 2612 623 ) via2_5 ++ NEW metal1 ( 3125 623 ) via1_4 ++ NEW metal2 ( 3125 623 ) via2_5 ; ++ - storage_4_0_0.bit4.d_pair0_b ( storage_4_0_0.bit4.dmux0_inv A ) ( storage_4_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 623 ) ( * 637 ) ++ NEW metal3 ( 3068 637 ) ( 3106 * ) ++ NEW metal1 ( 3106 623 ) via1_4 ++ NEW metal2 ( 3106 637 ) via2_5 ++ NEW metal1 ( 3068 637 ) via1_7 ++ NEW metal2 ( 3068 637 ) via2_5 ; ++ - storage_4_0_0.bit4.storage ( storage_4_0_0.bit4.obuf0 A ) ( storage_4_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 623 ) ( * 637 ) ++ NEW metal3 ( 2840 637 ) ( 2935 * ) ++ NEW metal1 ( 2935 623 ) via1_4 ++ NEW metal2 ( 2935 637 ) via2_5 ++ NEW metal1 ( 2840 637 ) via1_4 ++ NEW metal2 ( 2840 637 ) via2_5 ; ++ - storage_4_0_0.bit5.d ( storage_4_0_0.bit5.dmux0_inv ZN ) ( storage_4_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3239 623 ) ( 3752 * ) ++ NEW metal1 ( 3752 623 ) via1_4 ++ NEW metal2 ( 3752 623 ) via2_5 ++ NEW metal1 ( 3239 623 ) via1_4 ++ NEW metal2 ( 3239 623 ) via2_5 ; ++ - storage_4_0_0.bit5.d_pair0_b ( storage_4_0_0.bit5.dmux0_inv A ) ( storage_4_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 623 ) ( * 637 ) ++ NEW metal3 ( 3695 637 ) ( 3733 * ) ++ NEW metal1 ( 3733 623 ) via1_4 ++ NEW metal2 ( 3733 637 ) via2_5 ++ NEW metal1 ( 3695 637 ) via1_7 ++ NEW metal2 ( 3695 637 ) via2_5 ; ++ - storage_4_0_0.bit5.storage ( storage_4_0_0.bit5.obuf0 A ) ( storage_4_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3562 623 ) ( * 637 ) ++ NEW metal3 ( 3467 637 ) ( 3562 * ) ++ NEW metal1 ( 3562 623 ) via1_4 ++ NEW metal2 ( 3562 637 ) via2_5 ++ NEW metal1 ( 3467 637 ) via1_4 ++ NEW metal2 ( 3467 637 ) via2_5 ; ++ - storage_4_0_0.bit6.d ( storage_4_0_0.bit6.dmux0_inv ZN ) ( storage_4_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3866 623 ) ( 4379 * ) ++ NEW metal1 ( 3866 623 ) via1_4 ++ NEW metal2 ( 3866 623 ) via2_5 ++ NEW metal1 ( 4379 623 ) via1_4 ++ NEW metal2 ( 4379 623 ) via2_5 ; ++ - storage_4_0_0.bit6.d_pair0_b ( storage_4_0_0.bit6.dmux0_inv A ) ( storage_4_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 623 ) ( * 637 ) ++ NEW metal3 ( 4322 637 ) ( 4360 * ) ++ NEW metal1 ( 4360 623 ) via1_4 ++ NEW metal2 ( 4360 637 ) via2_5 ++ NEW metal1 ( 4322 637 ) via1_7 ++ NEW metal2 ( 4322 637 ) via2_5 ; ++ - storage_4_0_0.bit6.storage ( storage_4_0_0.bit6.obuf0 A ) ( storage_4_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4189 623 ) ( * 637 ) ++ NEW metal3 ( 4094 637 ) ( 4189 * ) ++ NEW metal1 ( 4189 623 ) via1_4 ++ NEW metal2 ( 4189 637 ) via2_5 ++ NEW metal1 ( 4094 637 ) via1_4 ++ NEW metal2 ( 4094 637 ) via2_5 ; ++ - storage_4_0_0.gclock ( storage_4_0_0.cg GCK ) ( storage_4_0_0.bit6.bit CK ) ( storage_4_0_0.bit5.bit CK ) ( storage_4_0_0.bit4.bit CK ) ( storage_4_0_0.bit3.bit CK ) ( storage_4_0_0.bit2.bit CK ) ( storage_4_0_0.bit1.bit CK ) ++ ( storage_4_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 595 ) ( * 623 ) ++ NEW metal2 ( 180 595 ) ( * 623 ) ++ NEW metal3 ( 180 595 ) ( 807 * ) ++ NEW metal2 ( 3942 609 ) ( * 623 ) ++ NEW metal3 ( 3453 595 ) ( * 609 ) ++ NEW metal3 ( 3453 609 ) ( 3942 * ) ++ NEW metal2 ( 3315 595 ) ( * 623 ) ++ NEW metal2 ( 2688 595 ) ( * 623 ) ++ NEW metal3 ( 2688 595 ) ( 3315 * ) ++ NEW metal2 ( 2061 595 ) ( * 623 ) ++ NEW metal3 ( 2061 595 ) ( 2688 * ) ++ NEW metal2 ( 1434 595 ) ( * 623 ) ++ NEW metal3 ( 1434 595 ) ( 2061 * ) ++ NEW metal3 ( 807 595 ) ( 1434 * ) ++ NEW metal3 ( 3315 595 ) ( 3453 * ) ++ NEW metal3 ( 3942 609 ) ( 4987 * ) ++ NEW metal1 ( 807 623 ) via1_4 ++ NEW metal2 ( 807 595 ) via2_5 ++ NEW metal1 ( 180 623 ) via1_4 ++ NEW metal2 ( 180 595 ) via2_5 ++ NEW metal1 ( 3942 623 ) via1_4 ++ NEW metal2 ( 3942 609 ) via2_5 ++ NEW metal1 ( 3315 623 ) via1_4 ++ NEW metal2 ( 3315 595 ) via2_5 ++ NEW metal1 ( 2688 623 ) via1_4 ++ NEW metal2 ( 2688 595 ) via2_5 ++ NEW metal1 ( 2061 623 ) via1_4 ++ NEW metal2 ( 2061 595 ) via2_5 ++ NEW metal1 ( 1434 623 ) via1_4 ++ NEW metal2 ( 1434 595 ) via2_5 ++ NEW metal1 ( 4987 609 ) via1_4 ++ NEW metal2 ( 4987 609 ) via2_5 ; ++ - storage_4_0_0.later0_b ( storage_4_0_0.take_and0 A2 ) ( storage_4_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 623 ) ( * 651 ) ++ NEW metal2 ( 4588 651 ) ( 4626 * ) ++ NEW metal1 ( 4626 623 ) via1_4 ++ NEW metal1 ( 4588 651 ) via1_4 ; ++ - storage_4_0_0.select0_b ( storage_4_0_0.select_inv_0 ZN ) ( storage_4_0_0.bit6.obuf0 EN ) ( storage_4_0_0.bit5.obuf0 EN ) ( storage_4_0_0.bit4.obuf0 EN ) ( storage_4_0_0.bit3.obuf0 EN ) ( storage_4_0_0.bit2.obuf0 EN ) ( storage_4_0_0.bit1.obuf0 EN ) ++ ( storage_4_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal3 ( 465 651 ) ( 1092 * ) ++ NEW metal2 ( 4227 651 ) ( * 679 ) ++ NEW metal2 ( 3600 651 ) ( * 679 ) ++ NEW metal3 ( 3600 679 ) ( 4227 * ) ++ NEW metal3 ( 2346 651 ) ( 2973 * ) ++ NEW metal3 ( 1719 651 ) ( 2346 * ) ++ NEW metal3 ( 1092 651 ) ( 1719 * ) ++ NEW metal3 ( 2973 651 ) ( 3600 * ) ++ NEW metal3 ( 4987 665 ) ( 5025 * ) ++ NEW metal3 ( 4987 665 ) ( * 679 ) ++ NEW metal3 ( 4227 679 ) ( 4987 * ) ++ NEW metal1 ( 1092 651 ) via1_4 ++ NEW metal2 ( 1092 651 ) via2_5 ++ NEW metal1 ( 465 651 ) via1_4 ++ NEW metal2 ( 465 651 ) via2_5 ++ NEW metal1 ( 4227 651 ) via1_4 ++ NEW metal2 ( 4227 679 ) via2_5 ++ NEW metal1 ( 3600 651 ) via1_4 ++ NEW metal2 ( 3600 679 ) via2_5 ++ NEW metal2 ( 3600 651 ) via2_5 ++ NEW metal1 ( 2973 651 ) via1_4 ++ NEW metal2 ( 2973 651 ) via2_5 ++ NEW metal1 ( 2346 651 ) via1_4 ++ NEW metal2 ( 2346 651 ) via2_5 ++ NEW metal1 ( 1719 651 ) via1_4 ++ NEW metal2 ( 1719 651 ) via2_5 ++ NEW metal1 ( 5025 665 ) via1_4 ++ NEW metal2 ( 5025 665 ) via2_5 ; ++ - storage_4_0_0.take0 ( storage_4_0_0.bit6.dmux0 A1 ) ( storage_4_0_0.bit5.dmux0 A1 ) ( storage_4_0_0.bit4.dmux0 A1 ) ( storage_4_0_0.bit3.dmux0 A1 ) ( storage_4_0_0.bit2.dmux0 A1 ) ( storage_4_0_0.bit1.dmux0 A1 ) ( storage_4_0_0.bit0.dmux0 A1 ) ++ ( storage_4_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 560 609 ) ( 1187 * ) ++ NEW metal2 ( 4322 595 ) ( * 609 ) ++ NEW metal2 ( 3695 595 ) ( * 609 ) ++ NEW metal3 ( 3695 595 ) ( 4322 * ) ++ NEW metal2 ( 3429 581 ) ( * 609 ) ++ NEW metal3 ( 3429 581 ) ( 3481 * ) ++ NEW metal3 ( 3481 581 ) ( * 595 ) ++ NEW metal3 ( 3481 595 ) ( 3695 * ) ++ NEW metal3 ( 1814 609 ) ( 2441 * ) ++ NEW metal3 ( 2441 609 ) ( 3068 * ) ++ NEW metal3 ( 1187 609 ) ( 1814 * ) ++ NEW metal3 ( 3068 609 ) ( 3429 * ) ++ NEW metal3 ( 4322 595 ) ( 4664 * ) ++ NEW metal1 ( 1187 609 ) via1_4 ++ NEW metal2 ( 1187 609 ) via2_5 ++ NEW metal1 ( 560 609 ) via1_4 ++ NEW metal2 ( 560 609 ) via2_5 ++ NEW metal1 ( 4322 609 ) via1_4 ++ NEW metal2 ( 4322 595 ) via2_5 ++ NEW metal1 ( 3695 609 ) via1_4 ++ NEW metal2 ( 3695 595 ) via2_5 ++ NEW metal2 ( 3429 609 ) via2_5 ++ NEW metal2 ( 3429 581 ) via2_5 ++ NEW metal1 ( 1814 609 ) via1_4 ++ NEW metal2 ( 1814 609 ) via2_5 ++ NEW metal1 ( 2441 609 ) via1_4 ++ NEW metal2 ( 2441 609 ) via2_5 ++ NEW metal1 ( 3068 609 ) via1_4 ++ NEW metal2 ( 3068 609 ) via2_5 ++ NEW metal1 ( 4664 595 ) via1_4 ++ NEW metal2 ( 4664 595 ) via2_5 ; ++ - storage_4_0_0.we ( storage_4_0_0.cg E ) ( storage_4_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 623 ) ( 4854 * ) ++ NEW metal1 ( 4854 623 ) via1_4 ++ NEW metal2 ( 4854 623 ) via2_5 ++ NEW metal1 ( 4740 623 ) via1_4 ++ NEW metal2 ( 4740 623 ) via2_5 ; ++ - storage_4_0_0.we0 ( storage_4_0_0.any_or0 A2 ) ( storage_4_0_0.take_and0 A1 ) ( storage_4_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 623 ) ( 4702 * ) ++ NEW metal3 ( 4474 623 ) ( 4607 * ) ++ NEW metal1 ( 4474 623 ) via1_4 ++ NEW metal2 ( 4474 623 ) via2_5 ++ NEW metal1 ( 4607 623 ) via1_4 ++ NEW metal2 ( 4607 623 ) via2_5 ++ NEW metal1 ( 4702 623 ) via1_4 ++ NEW metal2 ( 4702 623 ) via2_5 ; ++ - storage_4_0_0.we1 ( storage_4_0_0.bit6.dmux0 B1 ) ( storage_4_0_0.bit5.dmux0 B1 ) ( storage_4_0_0.bit4.dmux0 B1 ) ( storage_4_0_0.bit3.dmux0 B1 ) ( storage_4_0_0.bit2.dmux0 B1 ) ( storage_4_0_0.bit1.dmux0 B1 ) ( storage_4_0_0.bit0.dmux0 B1 ) ++ ( storage_4_0_0.any_or0 A1 ) ( storage_4_0_0.later_inv0 A ) ( storage_4_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 623 ) ( * 665 ) ++ NEW metal3 ( 522 665 ) ( 1149 * ) ++ NEW metal2 ( 522 623 ) ( * 665 ) ++ NEW metal2 ( 3657 623 ) ( * 665 ) ++ NEW metal2 ( 4284 623 ) ( * 665 ) ++ NEW metal3 ( 3657 665 ) ( 4284 * ) ++ NEW metal3 ( 4284 665 ) ( 4550 * ) ++ NEW metal2 ( 3030 623 ) ( * 665 ) ++ NEW metal2 ( 2403 623 ) ( * 665 ) ++ NEW metal3 ( 2403 665 ) ( 3030 * ) ++ NEW metal2 ( 1776 623 ) ( * 665 ) ++ NEW metal3 ( 1776 665 ) ( 2403 * ) ++ NEW metal3 ( 1149 665 ) ( 1776 * ) ++ NEW metal3 ( 3030 665 ) ( 3657 * ) ++ NEW metal2 ( 4683 623 ) ( * 665 ) ++ NEW metal2 ( 4569 623 ) ( * 665 ) ++ NEW metal2 ( 4550 665 ) ( 4569 * ) ++ NEW metal3 ( 4550 665 ) ( 4683 * ) ++ NEW metal1 ( 1149 623 ) via1_4 ++ NEW metal2 ( 1149 665 ) via2_5 ++ NEW metal2 ( 522 665 ) via2_5 ++ NEW metal1 ( 522 623 ) via1_4 ++ NEW metal1 ( 3657 623 ) via1_4 ++ NEW metal2 ( 3657 665 ) via2_5 ++ NEW metal1 ( 4284 623 ) via1_4 ++ NEW metal2 ( 4284 665 ) via2_5 ++ NEW metal1 ( 4550 665 ) via1_4 ++ NEW metal2 ( 4550 665 ) via2_5 ++ NEW metal1 ( 3030 623 ) via1_4 ++ NEW metal2 ( 3030 665 ) via2_5 ++ NEW metal1 ( 2403 623 ) via1_4 ++ NEW metal2 ( 2403 665 ) via2_5 ++ NEW metal1 ( 1776 623 ) via1_4 ++ NEW metal2 ( 1776 665 ) via2_5 ++ NEW metal2 ( 4683 665 ) via2_5 ++ NEW metal1 ( 4683 623 ) via1_4 ++ NEW metal1 ( 4569 623 ) via1_4 ; ++ - storage_5_0_0.bit0.d ( storage_5_0_0.bit0.dmux0_inv ZN ) ( storage_5_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 104 777 ) ( 617 * ) ++ NEW metal1 ( 104 777 ) via1_4 ++ NEW metal2 ( 104 777 ) via2_5 ++ NEW metal1 ( 617 777 ) via1_4 ++ NEW metal2 ( 617 777 ) via2_5 ; ++ - storage_5_0_0.bit0.d_pair0_b ( storage_5_0_0.bit0.dmux0_inv A ) ( storage_5_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 763 ) ( * 777 ) ++ NEW metal3 ( 560 763 ) ( 598 * ) ++ NEW metal1 ( 598 777 ) via1_4 ++ NEW metal2 ( 598 763 ) via2_5 ++ NEW metal1 ( 560 763 ) via1_7 ++ NEW metal2 ( 560 763 ) via2_5 ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.obuf0 A ) ( storage_5_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 427 777 ) ( * 791 ) ++ NEW metal3 ( 332 791 ) ( 427 * ) ++ NEW metal1 ( 427 777 ) via1_4 ++ NEW metal2 ( 427 791 ) via2_5 ++ NEW metal1 ( 332 791 ) via1_4 ++ NEW metal2 ( 332 791 ) via2_5 ; ++ - storage_5_0_0.bit1.d ( storage_5_0_0.bit1.dmux0_inv ZN ) ( storage_5_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 731 777 ) ( 1244 * ) ++ NEW metal1 ( 731 777 ) via1_4 ++ NEW metal2 ( 731 777 ) via2_5 ++ NEW metal1 ( 1244 777 ) via1_4 ++ NEW metal2 ( 1244 777 ) via2_5 ; ++ - storage_5_0_0.bit1.d_pair0_b ( storage_5_0_0.bit1.dmux0_inv A ) ( storage_5_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 763 ) ( * 777 ) ++ NEW metal3 ( 1187 763 ) ( 1225 * ) ++ NEW metal1 ( 1225 777 ) via1_4 ++ NEW metal2 ( 1225 763 ) via2_5 ++ NEW metal1 ( 1187 763 ) via1_7 ++ NEW metal2 ( 1187 763 ) via2_5 ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.obuf0 A ) ( storage_5_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1054 777 ) ( * 791 ) ++ NEW metal3 ( 959 791 ) ( 1054 * ) ++ NEW metal1 ( 1054 777 ) via1_4 ++ NEW metal2 ( 1054 791 ) via2_5 ++ NEW metal1 ( 959 791 ) via1_4 ++ NEW metal2 ( 959 791 ) via2_5 ; ++ - storage_5_0_0.bit2.d ( storage_5_0_0.bit2.dmux0_inv ZN ) ( storage_5_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1358 777 ) ( 1871 * ) ++ NEW metal1 ( 1358 777 ) via1_4 ++ NEW metal2 ( 1358 777 ) via2_5 ++ NEW metal1 ( 1871 777 ) via1_4 ++ NEW metal2 ( 1871 777 ) via2_5 ; ++ - storage_5_0_0.bit2.d_pair0_b ( storage_5_0_0.bit2.dmux0_inv A ) ( storage_5_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 763 ) ( * 777 ) ++ NEW metal3 ( 1814 763 ) ( 1852 * ) ++ NEW metal1 ( 1852 777 ) via1_4 ++ NEW metal2 ( 1852 763 ) via2_5 ++ NEW metal1 ( 1814 763 ) via1_7 ++ NEW metal2 ( 1814 763 ) via2_5 ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.obuf0 A ) ( storage_5_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1681 777 ) ( * 791 ) ++ NEW metal3 ( 1586 791 ) ( 1681 * ) ++ NEW metal1 ( 1681 777 ) via1_4 ++ NEW metal2 ( 1681 791 ) via2_5 ++ NEW metal1 ( 1586 791 ) via1_4 ++ NEW metal2 ( 1586 791 ) via2_5 ; ++ - storage_5_0_0.bit3.d ( storage_5_0_0.bit3.dmux0_inv ZN ) ( storage_5_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 1985 777 ) ( 2498 * ) ++ NEW metal1 ( 1985 777 ) via1_4 ++ NEW metal2 ( 1985 777 ) via2_5 ++ NEW metal1 ( 2498 777 ) via1_4 ++ NEW metal2 ( 2498 777 ) via2_5 ; ++ - storage_5_0_0.bit3.d_pair0_b ( storage_5_0_0.bit3.dmux0_inv A ) ( storage_5_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 763 ) ( * 777 ) ++ NEW metal3 ( 2441 763 ) ( 2479 * ) ++ NEW metal1 ( 2479 777 ) via1_4 ++ NEW metal2 ( 2479 763 ) via2_5 ++ NEW metal1 ( 2441 763 ) via1_7 ++ NEW metal2 ( 2441 763 ) via2_5 ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.obuf0 A ) ( storage_5_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 777 ) ( * 791 ) ++ NEW metal3 ( 2213 791 ) ( 2308 * ) ++ NEW metal1 ( 2308 777 ) via1_4 ++ NEW metal2 ( 2308 791 ) via2_5 ++ NEW metal1 ( 2213 791 ) via1_4 ++ NEW metal2 ( 2213 791 ) via2_5 ; ++ - storage_5_0_0.bit4.d ( storage_5_0_0.bit4.dmux0_inv ZN ) ( storage_5_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 2612 777 ) ( 3125 * ) ++ NEW metal1 ( 2612 777 ) via1_4 ++ NEW metal2 ( 2612 777 ) via2_5 ++ NEW metal1 ( 3125 777 ) via1_4 ++ NEW metal2 ( 3125 777 ) via2_5 ; ++ - storage_5_0_0.bit4.d_pair0_b ( storage_5_0_0.bit4.dmux0_inv A ) ( storage_5_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 763 ) ( * 777 ) ++ NEW metal3 ( 3068 763 ) ( 3106 * ) ++ NEW metal1 ( 3106 777 ) via1_4 ++ NEW metal2 ( 3106 763 ) via2_5 ++ NEW metal1 ( 3068 763 ) via1_7 ++ NEW metal2 ( 3068 763 ) via2_5 ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.obuf0 A ) ( storage_5_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 777 ) ( * 791 ) ++ NEW metal3 ( 2840 791 ) ( 2935 * ) ++ NEW metal1 ( 2935 777 ) via1_4 ++ NEW metal2 ( 2935 791 ) via2_5 ++ NEW metal1 ( 2840 791 ) via1_4 ++ NEW metal2 ( 2840 791 ) via2_5 ; ++ - storage_5_0_0.bit5.d ( storage_5_0_0.bit5.dmux0_inv ZN ) ( storage_5_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3239 777 ) ( 3752 * ) ++ NEW metal1 ( 3752 777 ) via1_4 ++ NEW metal2 ( 3752 777 ) via2_5 ++ NEW metal1 ( 3239 777 ) via1_4 ++ NEW metal2 ( 3239 777 ) via2_5 ; ++ - storage_5_0_0.bit5.d_pair0_b ( storage_5_0_0.bit5.dmux0_inv A ) ( storage_5_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 763 ) ( * 777 ) ++ NEW metal3 ( 3695 763 ) ( 3733 * ) ++ NEW metal1 ( 3733 777 ) via1_4 ++ NEW metal2 ( 3733 763 ) via2_5 ++ NEW metal1 ( 3695 763 ) via1_7 ++ NEW metal2 ( 3695 763 ) via2_5 ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.obuf0 A ) ( storage_5_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3562 777 ) ( * 791 ) ++ NEW metal3 ( 3467 791 ) ( 3562 * ) ++ NEW metal1 ( 3562 777 ) via1_4 ++ NEW metal2 ( 3562 791 ) via2_5 ++ NEW metal1 ( 3467 791 ) via1_4 ++ NEW metal2 ( 3467 791 ) via2_5 ; ++ - storage_5_0_0.bit6.d ( storage_5_0_0.bit6.dmux0_inv ZN ) ( storage_5_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal3 ( 3866 777 ) ( 4379 * ) ++ NEW metal1 ( 3866 777 ) via1_4 ++ NEW metal2 ( 3866 777 ) via2_5 ++ NEW metal1 ( 4379 777 ) via1_4 ++ NEW metal2 ( 4379 777 ) via2_5 ; ++ - storage_5_0_0.bit6.d_pair0_b ( storage_5_0_0.bit6.dmux0_inv A ) ( storage_5_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 763 ) ( * 777 ) ++ NEW metal3 ( 4322 763 ) ( 4360 * ) ++ NEW metal1 ( 4360 777 ) via1_4 ++ NEW metal2 ( 4360 763 ) via2_5 ++ NEW metal1 ( 4322 763 ) via1_7 ++ NEW metal2 ( 4322 763 ) via2_5 ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.obuf0 A ) ( storage_5_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4189 777 ) ( * 791 ) ++ NEW metal3 ( 4094 791 ) ( 4189 * ) ++ NEW metal1 ( 4189 777 ) via1_4 ++ NEW metal2 ( 4189 791 ) via2_5 ++ NEW metal1 ( 4094 791 ) via1_4 ++ NEW metal2 ( 4094 791 ) via2_5 ; ++ - storage_5_0_0.gclock ( storage_5_0_0.cg GCK ) ( storage_5_0_0.bit6.bit CK ) ( storage_5_0_0.bit5.bit CK ) ( storage_5_0_0.bit4.bit CK ) ( storage_5_0_0.bit3.bit CK ) ( storage_5_0_0.bit2.bit CK ) ( storage_5_0_0.bit1.bit CK ) ++ ( storage_5_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 777 ) ( * 805 ) ++ NEW metal2 ( 180 777 ) ( * 805 ) ++ NEW metal3 ( 180 805 ) ( 807 * ) ++ NEW metal2 ( 3942 777 ) ( * 805 ) ++ NEW metal2 ( 3315 777 ) ( * 805 ) ++ NEW metal2 ( 2688 777 ) ( * 805 ) ++ NEW metal3 ( 2688 805 ) ( 3315 * ) ++ NEW metal2 ( 2061 777 ) ( * 805 ) ++ NEW metal3 ( 2061 805 ) ( 2688 * ) ++ NEW metal2 ( 1434 777 ) ( * 805 ) ++ NEW metal3 ( 1434 805 ) ( 2061 * ) ++ NEW metal3 ( 807 805 ) ( 1434 * ) ++ NEW metal3 ( 3315 805 ) ( 3942 * ) ++ NEW metal3 ( 3942 805 ) ( 4987 * ) ++ NEW metal1 ( 807 777 ) via1_4 ++ NEW metal2 ( 807 805 ) via2_5 ++ NEW metal1 ( 180 777 ) via1_4 ++ NEW metal2 ( 180 805 ) via2_5 ++ NEW metal1 ( 3942 777 ) via1_4 ++ NEW metal2 ( 3942 805 ) via2_5 ++ NEW metal1 ( 3315 777 ) via1_4 ++ NEW metal2 ( 3315 805 ) via2_5 ++ NEW metal1 ( 2688 777 ) via1_4 ++ NEW metal2 ( 2688 805 ) via2_5 ++ NEW metal1 ( 2061 777 ) via1_4 ++ NEW metal2 ( 2061 805 ) via2_5 ++ NEW metal1 ( 1434 777 ) via1_4 ++ NEW metal2 ( 1434 805 ) via2_5 ++ NEW metal1 ( 4987 805 ) via1_4 ++ NEW metal2 ( 4987 805 ) via2_5 ; ++ - storage_5_0_0.later0_b ( storage_5_0_0.take_and0 A2 ) ( storage_5_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 777 ) ( * 805 ) ++ NEW metal2 ( 4588 805 ) ( 4626 * ) ++ NEW metal1 ( 4626 777 ) via1_4 ++ NEW metal1 ( 4588 805 ) via1_4 ; ++ - storage_5_0_0.select0_b ( storage_5_0_0.select_inv_0 ZN ) ( storage_5_0_0.bit6.obuf0 EN ) ( storage_5_0_0.bit5.obuf0 EN ) ( storage_5_0_0.bit4.obuf0 EN ) ( storage_5_0_0.bit3.obuf0 EN ) ( storage_5_0_0.bit2.obuf0 EN ) ( storage_5_0_0.bit1.obuf0 EN ) ++ ( storage_5_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal3 ( 465 749 ) ( 1092 * ) ++ NEW metal3 ( 3600 749 ) ( 4227 * ) ++ NEW metal2 ( 3600 721 ) ( * 749 ) ++ NEW metal2 ( 2973 721 ) ( * 749 ) ++ NEW metal2 ( 2346 721 ) ( * 749 ) ++ NEW metal3 ( 2346 721 ) ( 2973 * ) ++ NEW metal2 ( 1719 721 ) ( * 749 ) ++ NEW metal3 ( 1719 721 ) ( 2346 * ) ++ NEW metal3 ( 1092 749 ) ( 1719 * ) ++ NEW metal3 ( 2973 721 ) ( 3600 * ) ++ NEW metal3 ( 4227 749 ) ( 5025 * ) ++ NEW metal1 ( 1092 749 ) via1_4 ++ NEW metal2 ( 1092 749 ) via2_5 ++ NEW metal1 ( 465 749 ) via1_4 ++ NEW metal2 ( 465 749 ) via2_5 ++ NEW metal1 ( 4227 749 ) via1_4 ++ NEW metal2 ( 4227 749 ) via2_5 ++ NEW metal1 ( 3600 749 ) via1_4 ++ NEW metal2 ( 3600 749 ) via2_5 ++ NEW metal2 ( 3600 721 ) via2_5 ++ NEW metal1 ( 2973 749 ) via1_4 ++ NEW metal2 ( 2973 721 ) via2_5 ++ NEW metal1 ( 2346 749 ) via1_4 ++ NEW metal2 ( 2346 721 ) via2_5 ++ NEW metal1 ( 1719 749 ) via1_4 ++ NEW metal2 ( 1719 721 ) via2_5 ++ NEW metal2 ( 1719 749 ) via2_5 ++ NEW metal1 ( 5025 749 ) via1_4 ++ NEW metal2 ( 5025 749 ) via2_5 ; ++ - storage_5_0_0.take0 ( storage_5_0_0.bit6.dmux0 A1 ) ( storage_5_0_0.bit5.dmux0 A1 ) ( storage_5_0_0.bit4.dmux0 A1 ) ( storage_5_0_0.bit3.dmux0 A1 ) ( storage_5_0_0.bit2.dmux0 A1 ) ( storage_5_0_0.bit1.dmux0 A1 ) ( storage_5_0_0.bit0.dmux0 A1 ) ++ ( storage_5_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1187 791 ) ( * 819 ) ++ NEW metal3 ( 560 819 ) ( 1187 * ) ++ NEW metal2 ( 560 791 ) ( * 819 ) ++ NEW metal2 ( 3695 791 ) ( * 819 ) ++ NEW metal2 ( 4322 791 ) ( * 819 ) ++ NEW metal3 ( 3695 819 ) ( 4322 * ) ++ NEW metal2 ( 1814 791 ) ( * 819 ) ++ NEW metal2 ( 2441 791 ) ( * 819 ) ++ NEW metal3 ( 1814 819 ) ( 2441 * ) ++ NEW metal2 ( 3068 791 ) ( * 819 ) ++ NEW metal3 ( 2441 819 ) ( 3068 * ) ++ NEW metal3 ( 1187 819 ) ( 1814 * ) ++ NEW metal3 ( 3068 819 ) ( 3695 * ) ++ NEW metal3 ( 4322 819 ) ( 4664 * ) ++ NEW metal1 ( 1187 791 ) via1_4 ++ NEW metal2 ( 1187 819 ) via2_5 ++ NEW metal2 ( 560 819 ) via2_5 ++ NEW metal1 ( 560 791 ) via1_4 ++ NEW metal1 ( 3695 791 ) via1_4 ++ NEW metal2 ( 3695 819 ) via2_5 ++ NEW metal1 ( 4322 791 ) via1_4 ++ NEW metal2 ( 4322 819 ) via2_5 ++ NEW metal1 ( 1814 791 ) via1_4 ++ NEW metal2 ( 1814 819 ) via2_5 ++ NEW metal1 ( 2441 791 ) via1_4 ++ NEW metal2 ( 2441 819 ) via2_5 ++ NEW metal1 ( 3068 791 ) via1_4 ++ NEW metal2 ( 3068 819 ) via2_5 ++ NEW metal1 ( 4664 819 ) via1_7 ++ NEW metal2 ( 4664 819 ) via2_5 ; ++ - storage_5_0_0.we ( storage_5_0_0.cg E ) ( storage_5_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 777 ) ( 4854 * ) ++ NEW metal1 ( 4854 777 ) via1_4 ++ NEW metal2 ( 4854 777 ) via2_5 ++ NEW metal1 ( 4740 777 ) via1_4 ++ NEW metal2 ( 4740 777 ) via2_5 ; ++ - storage_5_0_0.we0 ( storage_5_0_0.any_or0 A2 ) ( storage_5_0_0.take_and0 A1 ) ( storage_5_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 777 ) ( 4702 * ) ++ NEW metal3 ( 4474 777 ) ( 4607 * ) ++ NEW metal1 ( 4474 777 ) via1_4 ++ NEW metal2 ( 4474 777 ) via2_5 ++ NEW metal1 ( 4607 777 ) via1_4 ++ NEW metal2 ( 4607 777 ) via2_5 ++ NEW metal1 ( 4702 777 ) via1_4 ++ NEW metal2 ( 4702 777 ) via2_5 ; ++ - storage_5_0_0.we1 ( storage_5_0_0.bit6.dmux0 B1 ) ( storage_5_0_0.bit5.dmux0 B1 ) ( storage_5_0_0.bit4.dmux0 B1 ) ( storage_5_0_0.bit3.dmux0 B1 ) ( storage_5_0_0.bit2.dmux0 B1 ) ( storage_5_0_0.bit1.dmux0 B1 ) ( storage_5_0_0.bit0.dmux0 B1 ) ++ ( storage_5_0_0.any_or0 A1 ) ( storage_5_0_0.later_inv0 A ) ( storage_5_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 735 ) ( * 777 ) ++ NEW metal3 ( 522 735 ) ( 1149 * ) ++ NEW metal2 ( 522 735 ) ( * 777 ) ++ NEW metal2 ( 3657 763 ) ( * 777 ) ++ NEW metal2 ( 4284 735 ) ( * 777 ) ++ NEW metal3 ( 3657 735 ) ( 4284 * ) ++ NEW metal2 ( 3657 735 ) ( * 763 ) ++ NEW metal3 ( 4284 735 ) ( 4550 * ) ++ NEW metal2 ( 4550 735 ) ( * 777 ) ++ NEW metal3 ( 3420 763 ) ( 3657 * ) ++ NEW metal2 ( 1776 735 ) ( * 777 ) ++ NEW metal2 ( 2403 735 ) ( * 777 ) ++ NEW metal3 ( 1776 735 ) ( 2403 * ) ++ NEW metal2 ( 3030 735 ) ( * 777 ) ++ NEW metal3 ( 2403 735 ) ( 3030 * ) ++ NEW metal3 ( 3420 735 ) ( * 763 ) ++ NEW metal3 ( 3030 735 ) ( 3420 * ) ++ NEW metal3 ( 1149 735 ) ( 1776 * ) ++ NEW metal2 ( 4683 735 ) ( * 777 ) ++ NEW metal3 ( 4550 735 ) ( 4683 * ) ++ NEW metal2 ( 4550 777 ) ( 4569 * ) ++ NEW metal1 ( 1149 777 ) via1_4 ++ NEW metal2 ( 1149 735 ) via2_5 ++ NEW metal2 ( 522 735 ) via2_5 ++ NEW metal1 ( 522 777 ) via1_4 ++ NEW metal1 ( 3657 777 ) via1_4 ++ NEW metal2 ( 3657 763 ) via2_5 ++ NEW metal1 ( 4284 777 ) via1_4 ++ NEW metal2 ( 4284 735 ) via2_5 ++ NEW metal2 ( 3657 735 ) via2_5 ++ NEW metal1 ( 4550 735 ) via1_4 ++ NEW metal2 ( 4550 735 ) via2_5 ++ NEW metal1 ( 1776 777 ) via1_4 ++ NEW metal2 ( 1776 735 ) via2_5 ++ NEW metal1 ( 2403 777 ) via1_4 ++ NEW metal2 ( 2403 735 ) via2_5 ++ NEW metal1 ( 3030 777 ) via1_4 ++ NEW metal2 ( 3030 735 ) via2_5 ++ NEW metal2 ( 4683 735 ) via2_5 ++ NEW metal1 ( 4683 777 ) via1_4 ++ NEW metal1 ( 4569 777 ) via1_4 ; ++ - storage_6_0_0.bit0.d ( storage_6_0_0.bit0.dmux0_inv ZN ) ( storage_6_0_0.bit0.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 104 889 ) ( * 903 ) ++ NEW metal3 ( 104 889 ) ( 617 * ) ++ NEW metal1 ( 104 903 ) via1_4 ++ NEW metal2 ( 104 889 ) via2_5 ++ NEW metal1 ( 617 889 ) via1_4 ++ NEW metal2 ( 617 889 ) via2_5 ; ++ - storage_6_0_0.bit0.d_pair0_b ( storage_6_0_0.bit0.dmux0_inv A ) ( storage_6_0_0.bit0.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 598 903 ) ( * 917 ) ++ NEW metal3 ( 560 917 ) ( 598 * ) ++ NEW metal1 ( 598 903 ) via1_4 ++ NEW metal2 ( 598 917 ) via2_5 ++ NEW metal1 ( 560 917 ) via1_7 ++ NEW metal2 ( 560 917 ) via2_5 ; ++ - storage_6_0_0.bit0.storage ( storage_6_0_0.bit0.obuf0 A ) ( storage_6_0_0.bit0.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 427 903 ) ( * 917 ) ++ NEW metal3 ( 332 917 ) ( 427 * ) ++ NEW metal1 ( 427 903 ) via1_4 ++ NEW metal2 ( 427 917 ) via2_5 ++ NEW metal1 ( 332 917 ) via1_4 ++ NEW metal2 ( 332 917 ) via2_5 ; ++ - storage_6_0_0.bit1.d ( storage_6_0_0.bit1.dmux0_inv ZN ) ( storage_6_0_0.bit1.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 731 889 ) ( * 903 ) ++ NEW metal3 ( 731 889 ) ( 1244 * ) ++ NEW metal1 ( 731 903 ) via1_4 ++ NEW metal2 ( 731 889 ) via2_5 ++ NEW metal1 ( 1244 889 ) via1_4 ++ NEW metal2 ( 1244 889 ) via2_5 ; ++ - storage_6_0_0.bit1.d_pair0_b ( storage_6_0_0.bit1.dmux0_inv A ) ( storage_6_0_0.bit1.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1225 903 ) ( * 917 ) ++ NEW metal3 ( 1187 917 ) ( 1225 * ) ++ NEW metal1 ( 1225 903 ) via1_4 ++ NEW metal2 ( 1225 917 ) via2_5 ++ NEW metal1 ( 1187 917 ) via1_7 ++ NEW metal2 ( 1187 917 ) via2_5 ; ++ - storage_6_0_0.bit1.storage ( storage_6_0_0.bit1.obuf0 A ) ( storage_6_0_0.bit1.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1054 903 ) ( * 917 ) ++ NEW metal3 ( 959 917 ) ( 1054 * ) ++ NEW metal1 ( 1054 903 ) via1_4 ++ NEW metal2 ( 1054 917 ) via2_5 ++ NEW metal1 ( 959 917 ) via1_4 ++ NEW metal2 ( 959 917 ) via2_5 ; ++ - storage_6_0_0.bit2.d ( storage_6_0_0.bit2.dmux0_inv ZN ) ( storage_6_0_0.bit2.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 1358 889 ) ( * 903 ) ++ NEW metal3 ( 1358 889 ) ( 1871 * ) ++ NEW metal1 ( 1358 903 ) via1_4 ++ NEW metal2 ( 1358 889 ) via2_5 ++ NEW metal1 ( 1871 889 ) via1_4 ++ NEW metal2 ( 1871 889 ) via2_5 ; ++ - storage_6_0_0.bit2.d_pair0_b ( storage_6_0_0.bit2.dmux0_inv A ) ( storage_6_0_0.bit2.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1852 903 ) ( * 917 ) ++ NEW metal3 ( 1814 917 ) ( 1852 * ) ++ NEW metal1 ( 1852 903 ) via1_4 ++ NEW metal2 ( 1852 917 ) via2_5 ++ NEW metal1 ( 1814 917 ) via1_7 ++ NEW metal2 ( 1814 917 ) via2_5 ; ++ - storage_6_0_0.bit2.storage ( storage_6_0_0.bit2.obuf0 A ) ( storage_6_0_0.bit2.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 1681 903 ) ( * 917 ) ++ NEW metal3 ( 1586 917 ) ( 1681 * ) ++ NEW metal1 ( 1681 903 ) via1_4 ++ NEW metal2 ( 1681 917 ) via2_5 ++ NEW metal1 ( 1586 917 ) via1_4 ++ NEW metal2 ( 1586 917 ) via2_5 ; ++ - storage_6_0_0.bit3.d ( storage_6_0_0.bit3.dmux0_inv ZN ) ( storage_6_0_0.bit3.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 1985 889 ) ( * 903 ) ++ NEW metal3 ( 1985 889 ) ( 2498 * ) ++ NEW metal1 ( 1985 903 ) via1_4 ++ NEW metal2 ( 1985 889 ) via2_5 ++ NEW metal1 ( 2498 889 ) via1_4 ++ NEW metal2 ( 2498 889 ) via2_5 ; ++ - storage_6_0_0.bit3.d_pair0_b ( storage_6_0_0.bit3.dmux0_inv A ) ( storage_6_0_0.bit3.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 2479 903 ) ( * 917 ) ++ NEW metal3 ( 2441 917 ) ( 2479 * ) ++ NEW metal1 ( 2479 903 ) via1_4 ++ NEW metal2 ( 2479 917 ) via2_5 ++ NEW metal1 ( 2441 917 ) via1_7 ++ NEW metal2 ( 2441 917 ) via2_5 ; ++ - storage_6_0_0.bit3.storage ( storage_6_0_0.bit3.obuf0 A ) ( storage_6_0_0.bit3.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2308 903 ) ( * 917 ) ++ NEW metal3 ( 2213 917 ) ( 2308 * ) ++ NEW metal1 ( 2308 903 ) via1_4 ++ NEW metal2 ( 2308 917 ) via2_5 ++ NEW metal1 ( 2213 917 ) via1_4 ++ NEW metal2 ( 2213 917 ) via2_5 ; ++ - storage_6_0_0.bit4.d ( storage_6_0_0.bit4.dmux0_inv ZN ) ( storage_6_0_0.bit4.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 2612 889 ) ( * 903 ) ++ NEW metal3 ( 2612 889 ) ( 3125 * ) ++ NEW metal1 ( 2612 903 ) via1_4 ++ NEW metal2 ( 2612 889 ) via2_5 ++ NEW metal1 ( 3125 889 ) via1_4 ++ NEW metal2 ( 3125 889 ) via2_5 ; ++ - storage_6_0_0.bit4.d_pair0_b ( storage_6_0_0.bit4.dmux0_inv A ) ( storage_6_0_0.bit4.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3106 903 ) ( * 917 ) ++ NEW metal3 ( 3068 917 ) ( 3106 * ) ++ NEW metal1 ( 3106 903 ) via1_4 ++ NEW metal2 ( 3106 917 ) via2_5 ++ NEW metal1 ( 3068 917 ) via1_7 ++ NEW metal2 ( 3068 917 ) via2_5 ; ++ - storage_6_0_0.bit4.storage ( storage_6_0_0.bit4.obuf0 A ) ( storage_6_0_0.bit4.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 2935 903 ) ( * 917 ) ++ NEW metal3 ( 2840 917 ) ( 2935 * ) ++ NEW metal1 ( 2935 903 ) via1_4 ++ NEW metal2 ( 2935 917 ) via2_5 ++ NEW metal1 ( 2840 917 ) via1_4 ++ NEW metal2 ( 2840 917 ) via2_5 ; ++ - storage_6_0_0.bit5.d ( storage_6_0_0.bit5.dmux0_inv ZN ) ( storage_6_0_0.bit5.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 3239 889 ) ( * 903 ) ++ NEW metal3 ( 3239 889 ) ( 3752 * ) ++ NEW metal1 ( 3752 889 ) via1_4 ++ NEW metal2 ( 3752 889 ) via2_5 ++ NEW metal1 ( 3239 903 ) via1_4 ++ NEW metal2 ( 3239 889 ) via2_5 ; ++ - storage_6_0_0.bit5.d_pair0_b ( storage_6_0_0.bit5.dmux0_inv A ) ( storage_6_0_0.bit5.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 3733 903 ) ( * 917 ) ++ NEW metal3 ( 3695 917 ) ( 3733 * ) ++ NEW metal1 ( 3733 903 ) via1_4 ++ NEW metal2 ( 3733 917 ) via2_5 ++ NEW metal1 ( 3695 917 ) via1_7 ++ NEW metal2 ( 3695 917 ) via2_5 ; ++ - storage_6_0_0.bit5.storage ( storage_6_0_0.bit5.obuf0 A ) ( storage_6_0_0.bit5.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 3562 903 ) ( * 917 ) ++ NEW metal3 ( 3467 917 ) ( 3562 * ) ++ NEW metal1 ( 3562 903 ) via1_4 ++ NEW metal2 ( 3562 917 ) via2_5 ++ NEW metal1 ( 3467 917 ) via1_4 ++ NEW metal2 ( 3467 917 ) via2_5 ; ++ - storage_6_0_0.bit6.d ( storage_6_0_0.bit6.dmux0_inv ZN ) ( storage_6_0_0.bit6.bit D ) + USE SIGNAL ++ + ROUTED metal2 ( 3866 889 ) ( * 903 ) ++ NEW metal3 ( 3866 889 ) ( 4379 * ) ++ NEW metal1 ( 3866 903 ) via1_4 ++ NEW metal2 ( 3866 889 ) via2_5 ++ NEW metal1 ( 4379 889 ) via1_4 ++ NEW metal2 ( 4379 889 ) via2_5 ; ++ - storage_6_0_0.bit6.d_pair0_b ( storage_6_0_0.bit6.dmux0_inv A ) ( storage_6_0_0.bit6.dmux0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4360 903 ) ( * 917 ) ++ NEW metal3 ( 4322 917 ) ( 4360 * ) ++ NEW metal1 ( 4360 903 ) via1_4 ++ NEW metal2 ( 4360 917 ) via2_5 ++ NEW metal1 ( 4322 917 ) via1_7 ++ NEW metal2 ( 4322 917 ) via2_5 ; ++ - storage_6_0_0.bit6.storage ( storage_6_0_0.bit6.obuf0 A ) ( storage_6_0_0.bit6.bit Q ) + USE SIGNAL ++ + ROUTED metal2 ( 4189 903 ) ( * 917 ) ++ NEW metal3 ( 4094 917 ) ( 4189 * ) ++ NEW metal1 ( 4189 903 ) via1_4 ++ NEW metal2 ( 4189 917 ) via2_5 ++ NEW metal1 ( 4094 917 ) via1_4 ++ NEW metal2 ( 4094 917 ) via2_5 ; ++ - storage_6_0_0.gclock ( storage_6_0_0.cg GCK ) ( storage_6_0_0.bit6.bit CK ) ( storage_6_0_0.bit5.bit CK ) ( storage_6_0_0.bit4.bit CK ) ( storage_6_0_0.bit3.bit CK ) ( storage_6_0_0.bit2.bit CK ) ( storage_6_0_0.bit1.bit CK ) ++ ( storage_6_0_0.bit0.bit CK ) + USE SIGNAL ++ + ROUTED metal2 ( 807 875 ) ( * 903 ) ++ NEW metal2 ( 180 875 ) ( * 903 ) ++ NEW metal3 ( 180 875 ) ( 807 * ) ++ NEW metal2 ( 3942 875 ) ( * 903 ) ++ NEW metal2 ( 3315 875 ) ( * 903 ) ++ NEW metal2 ( 2688 875 ) ( * 903 ) ++ NEW metal3 ( 2688 875 ) ( 3315 * ) ++ NEW metal2 ( 2061 875 ) ( * 903 ) ++ NEW metal3 ( 2061 875 ) ( 2688 * ) ++ NEW metal2 ( 1434 875 ) ( * 903 ) ++ NEW metal3 ( 1434 875 ) ( 2061 * ) ++ NEW metal3 ( 807 875 ) ( 1434 * ) ++ NEW metal3 ( 3315 875 ) ( 3942 * ) ++ NEW metal3 ( 3942 875 ) ( 4987 * ) ++ NEW metal1 ( 807 903 ) via1_4 ++ NEW metal2 ( 807 875 ) via2_5 ++ NEW metal1 ( 180 903 ) via1_4 ++ NEW metal2 ( 180 875 ) via2_5 ++ NEW metal1 ( 3942 903 ) via1_4 ++ NEW metal2 ( 3942 875 ) via2_5 ++ NEW metal1 ( 3315 903 ) via1_4 ++ NEW metal2 ( 3315 875 ) via2_5 ++ NEW metal1 ( 2688 903 ) via1_4 ++ NEW metal2 ( 2688 875 ) via2_5 ++ NEW metal1 ( 2061 903 ) via1_4 ++ NEW metal2 ( 2061 875 ) via2_5 ++ NEW metal1 ( 1434 903 ) via1_4 ++ NEW metal2 ( 1434 875 ) via2_5 ++ NEW metal1 ( 4987 875 ) via1_4 ++ NEW metal2 ( 4987 875 ) via2_5 ; ++ - storage_6_0_0.later0_b ( storage_6_0_0.take_and0 A2 ) ( storage_6_0_0.later_inv0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 4626 903 ) ( * 931 ) ++ NEW metal2 ( 4588 931 ) ( 4626 * ) ++ NEW metal1 ( 4626 903 ) via1_4 ++ NEW metal1 ( 4588 931 ) via1_4 ; ++ - storage_6_0_0.select0_b ( storage_6_0_0.select_inv_0 ZN ) ( storage_6_0_0.bit6.obuf0 EN ) ( storage_6_0_0.bit5.obuf0 EN ) ( storage_6_0_0.bit4.obuf0 EN ) ( storage_6_0_0.bit3.obuf0 EN ) ( storage_6_0_0.bit2.obuf0 EN ) ( storage_6_0_0.bit1.obuf0 EN ) ++ ( storage_6_0_0.bit0.obuf0 EN ) + USE SIGNAL ++ + ROUTED metal3 ( 465 931 ) ( 1092 * ) ++ NEW metal2 ( 4227 931 ) ( * 945 ) ++ NEW metal3 ( 3600 931 ) ( 4153 * ) ++ NEW metal3 ( 4153 931 ) ( * 945 ) ++ NEW metal3 ( 4153 945 ) ( 4227 * ) ++ NEW metal3 ( 2346 931 ) ( 2973 * ) ++ NEW metal3 ( 1719 931 ) ( 2346 * ) ++ NEW metal3 ( 1092 931 ) ( 1719 * ) ++ NEW metal3 ( 2973 931 ) ( 3600 * ) ++ NEW metal3 ( 4227 945 ) ( 5025 * ) ++ NEW metal1 ( 1092 931 ) via1_4 ++ NEW metal2 ( 1092 931 ) via2_5 ++ NEW metal1 ( 465 931 ) via1_4 ++ NEW metal2 ( 465 931 ) via2_5 ++ NEW metal1 ( 4227 931 ) via1_4 ++ NEW metal2 ( 4227 945 ) via2_5 ++ NEW metal1 ( 3600 931 ) via1_4 ++ NEW metal2 ( 3600 931 ) via2_5 ++ NEW metal1 ( 2973 931 ) via1_4 ++ NEW metal2 ( 2973 931 ) via2_5 ++ NEW metal1 ( 2346 931 ) via1_4 ++ NEW metal2 ( 2346 931 ) via2_5 ++ NEW metal1 ( 1719 931 ) via1_4 ++ NEW metal2 ( 1719 931 ) via2_5 ++ NEW metal1 ( 5025 945 ) via1_4 ++ NEW metal2 ( 5025 945 ) via2_5 ; ++ - storage_6_0_0.take0 ( storage_6_0_0.bit6.dmux0 A1 ) ( storage_6_0_0.bit5.dmux0 A1 ) ( storage_6_0_0.bit4.dmux0 A1 ) ( storage_6_0_0.bit3.dmux0 A1 ) ( storage_6_0_0.bit2.dmux0 A1 ) ( storage_6_0_0.bit1.dmux0 A1 ) ( storage_6_0_0.bit0.dmux0 A1 ) ++ ( storage_6_0_0.take_and0 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1187 861 ) ( * 889 ) ++ NEW metal3 ( 560 861 ) ( 1187 * ) ++ NEW metal2 ( 560 861 ) ( * 889 ) ++ NEW metal2 ( 4322 861 ) ( * 889 ) ++ NEW metal2 ( 3695 861 ) ( * 889 ) ++ NEW metal3 ( 3695 861 ) ( 4322 * ) ++ NEW metal2 ( 1814 861 ) ( * 889 ) ++ NEW metal2 ( 2441 861 ) ( * 889 ) ++ NEW metal3 ( 1814 861 ) ( 2441 * ) ++ NEW metal2 ( 3068 861 ) ( * 889 ) ++ NEW metal3 ( 2441 861 ) ( 3068 * ) ++ NEW metal3 ( 1187 861 ) ( 1814 * ) ++ NEW metal3 ( 3068 861 ) ( 3695 * ) ++ NEW metal3 ( 4322 861 ) ( 4664 * ) ++ NEW metal1 ( 1187 889 ) via1_4 ++ NEW metal2 ( 1187 861 ) via2_5 ++ NEW metal2 ( 560 861 ) via2_5 ++ NEW metal1 ( 560 889 ) via1_4 ++ NEW metal1 ( 4322 889 ) via1_4 ++ NEW metal2 ( 4322 861 ) via2_5 ++ NEW metal1 ( 3695 889 ) via1_4 ++ NEW metal2 ( 3695 861 ) via2_5 ++ NEW metal1 ( 1814 889 ) via1_4 ++ NEW metal2 ( 1814 861 ) via2_5 ++ NEW metal1 ( 2441 889 ) via1_4 ++ NEW metal2 ( 2441 861 ) via2_5 ++ NEW metal1 ( 3068 889 ) via1_4 ++ NEW metal2 ( 3068 861 ) via2_5 ++ NEW metal1 ( 4664 861 ) via1_7 ++ NEW metal2 ( 4664 861 ) via2_5 ; ++ - storage_6_0_0.we ( storage_6_0_0.cg E ) ( storage_6_0_0.any_or0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4740 903 ) ( 4854 * ) ++ NEW metal1 ( 4854 903 ) via1_4 ++ NEW metal2 ( 4854 903 ) via2_5 ++ NEW metal1 ( 4740 903 ) via1_4 ++ NEW metal2 ( 4740 903 ) via2_5 ; ++ - storage_6_0_0.we0 ( storage_6_0_0.any_or0 A2 ) ( storage_6_0_0.take_and0 A1 ) ( storage_6_0_0.gcand0 ZN ) + USE SIGNAL ++ + ROUTED metal3 ( 4607 903 ) ( 4702 * ) ++ NEW metal3 ( 4474 903 ) ( 4607 * ) ++ NEW metal1 ( 4474 903 ) via1_4 ++ NEW metal2 ( 4474 903 ) via2_5 ++ NEW metal1 ( 4607 903 ) via1_4 ++ NEW metal2 ( 4607 903 ) via2_5 ++ NEW metal1 ( 4702 903 ) via1_4 ++ NEW metal2 ( 4702 903 ) via2_5 ; ++ - storage_6_0_0.we1 ( storage_6_0_0.bit6.dmux0 B1 ) ( storage_6_0_0.bit5.dmux0 B1 ) ( storage_6_0_0.bit4.dmux0 B1 ) ( storage_6_0_0.bit3.dmux0 B1 ) ( storage_6_0_0.bit2.dmux0 B1 ) ( storage_6_0_0.bit1.dmux0 B1 ) ( storage_6_0_0.bit0.dmux0 B1 ) ++ ( storage_6_0_0.any_or0 A1 ) ( storage_6_0_0.later_inv0 A ) ( storage_6_0_0.gcand1 ZN ) + USE SIGNAL ++ + ROUTED metal2 ( 1149 903 ) ( * 959 ) ++ NEW metal3 ( 522 959 ) ( 1149 * ) ++ NEW metal2 ( 522 903 ) ( * 959 ) ++ NEW metal2 ( 3657 903 ) ( * 959 ) ++ NEW metal2 ( 4284 903 ) ( * 959 ) ++ NEW metal3 ( 3657 959 ) ( 4284 * ) ++ NEW metal3 ( 4284 959 ) ( 4550 * ) ++ NEW metal2 ( 3030 903 ) ( * 959 ) ++ NEW metal2 ( 2403 903 ) ( * 959 ) ++ NEW metal3 ( 2403 959 ) ( 3030 * ) ++ NEW metal2 ( 1776 903 ) ( * 959 ) ++ NEW metal3 ( 1776 959 ) ( 2403 * ) ++ NEW metal3 ( 1149 959 ) ( 1776 * ) ++ NEW metal3 ( 3030 959 ) ( 3657 * ) ++ NEW metal2 ( 4569 903 ) ( * 959 ) ++ NEW metal2 ( 4683 903 ) ( * 917 ) ++ NEW metal3 ( 4569 917 ) ( 4683 * ) ++ NEW metal2 ( 4550 959 ) ( 4569 * ) ++ NEW metal1 ( 1149 903 ) via1_4 ++ NEW metal2 ( 1149 959 ) via2_5 ++ NEW metal2 ( 522 959 ) via2_5 ++ NEW metal1 ( 522 903 ) via1_4 ++ NEW metal1 ( 3657 903 ) via1_4 ++ NEW metal2 ( 3657 959 ) via2_5 ++ NEW metal1 ( 4284 903 ) via1_4 ++ NEW metal2 ( 4284 959 ) via2_5 ++ NEW metal1 ( 4550 959 ) via1_7 ++ NEW metal2 ( 4550 959 ) via2_5 ++ NEW metal1 ( 3030 903 ) via1_4 ++ NEW metal2 ( 3030 959 ) via2_5 ++ NEW metal1 ( 2403 903 ) via1_4 ++ NEW metal2 ( 2403 959 ) via2_5 ++ NEW metal1 ( 1776 903 ) via1_4 ++ NEW metal2 ( 1776 959 ) via2_5 ++ NEW metal1 ( 4569 903 ) via1_4 ++ NEW metal1 ( 4683 903 ) via1_4 ++ NEW metal2 ( 4683 917 ) via2_5 ++ NEW metal2 ( 4569 917 ) via2_5 ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Z ) ( storage_0_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 35 ) ( * 63 ) ++ NEW metal3 ( 4417 35 ) ( 5082 * ) ++ NEW metal1 ( 4417 63 ) via1_4 ++ NEW metal2 ( 4417 35 ) via2_5 ++ NEW metal1 ( 5082 35 ) via1_4 ++ NEW metal2 ( 5082 35 ) via2_5 ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Z ) ( storage_1_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 203 ) ( * 217 ) ++ NEW metal2 ( 5063 161 ) ( * 203 ) ++ NEW metal2 ( 5063 161 ) ( 5082 * ) ++ NEW metal3 ( 4417 203 ) ( 5063 * ) ++ NEW metal1 ( 4417 217 ) via1_4 ++ NEW metal2 ( 4417 203 ) via2_5 ++ NEW metal2 ( 5063 203 ) via2_5 ++ NEW metal1 ( 5082 161 ) via1_7 ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Z ) ( storage_2_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 343 ) ( * 385 ) ++ NEW metal3 ( 4417 385 ) ( 5082 * ) ++ NEW metal1 ( 4417 343 ) via1_4 ++ NEW metal2 ( 4417 385 ) via2_5 ++ NEW metal1 ( 5082 385 ) via1_4 ++ NEW metal2 ( 5082 385 ) via2_5 ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Z ) ( storage_3_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 441 ) ( * 497 ) ++ NEW metal3 ( 4417 441 ) ( 5082 * ) ++ NEW metal1 ( 4417 497 ) via1_4 ++ NEW metal2 ( 4417 441 ) via2_5 ++ NEW metal1 ( 5082 441 ) via1_7 ++ NEW metal2 ( 5082 441 ) via2_5 ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Z ) ( storage_4_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 581 ) ( * 623 ) ++ NEW metal3 ( 4417 581 ) ( 5082 * ) ++ NEW metal1 ( 4417 623 ) via1_4 ++ NEW metal2 ( 4417 581 ) via2_5 ++ NEW metal1 ( 5082 581 ) via1_7 ++ NEW metal2 ( 5082 581 ) via2_5 ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Z ) ( storage_5_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 763 ) ( * 777 ) ++ NEW metal2 ( 4987 707 ) ( * 763 ) ++ NEW metal3 ( 4987 707 ) ( 5082 * ) ++ NEW metal2 ( 5082 707 ) ( * 721 ) ++ NEW metal3 ( 4417 763 ) ( 4987 * ) ++ NEW metal1 ( 4417 777 ) via1_4 ++ NEW metal2 ( 4417 763 ) via2_5 ++ NEW metal2 ( 4987 763 ) via2_5 ++ NEW metal2 ( 4987 707 ) via2_5 ++ NEW metal2 ( 5082 707 ) via2_5 ++ NEW metal1 ( 5082 721 ) via1_7 ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Z ) ( storage_6_0_0.gcand0 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4417 903 ) ( * 931 ) ++ NEW metal3 ( 4417 931 ) ( 5082 * ) ++ NEW metal1 ( 4417 903 ) via1_4 ++ NEW metal2 ( 4417 931 ) via2_5 ++ NEW metal1 ( 5082 931 ) via1_4 ++ NEW metal2 ( 5082 931 ) via2_5 ; ++ - w_sel_p1.select_w0 ( sel_buf_w_p1.sel_buf_0 Z ) ( storage_0_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 63 ) ( * 105 ) ++ NEW metal3 ( 4683 105 ) ( * 119 ) ++ NEW metal3 ( 4683 119 ) ( 5291 * ) ++ NEW metal3 ( 4493 105 ) ( 4683 * ) ++ NEW metal1 ( 4493 63 ) via1_4 ++ NEW metal2 ( 4493 105 ) via2_5 ++ NEW metal1 ( 5291 119 ) via1_7 ++ NEW metal2 ( 5291 119 ) via2_5 ; ++ - w_sel_p1.select_w1 ( sel_buf_w_p1.sel_buf_1 Z ) ( storage_1_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 217 ) ( * 231 ) ++ NEW metal3 ( 5006 231 ) ( * 259 ) ++ NEW metal3 ( 5006 259 ) ( 5291 * ) ++ NEW metal3 ( 4493 231 ) ( 5006 * ) ++ NEW metal1 ( 4493 217 ) via1_4 ++ NEW metal2 ( 4493 231 ) via2_5 ++ NEW metal1 ( 5291 259 ) via1_7 ++ NEW metal2 ( 5291 259 ) via2_5 ; ++ - w_sel_p1.select_w2 ( sel_buf_w_p1.sel_buf_2 Z ) ( storage_2_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 301 ) ( * 343 ) ++ NEW metal3 ( 4493 301 ) ( 4517 * ) ++ NEW metal3 ( 4517 287 ) ( * 301 ) ++ NEW metal2 ( 5291 287 ) ( * 301 ) ++ NEW metal3 ( 4517 287 ) ( 5291 * ) ++ NEW metal1 ( 4493 343 ) via1_4 ++ NEW metal2 ( 4493 301 ) via2_5 ++ NEW metal2 ( 5291 287 ) via2_5 ++ NEW metal1 ( 5291 301 ) via1_7 ; ++ - w_sel_p1.select_w3 ( sel_buf_w_p1.sel_buf_3 Z ) ( storage_3_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 455 ) ( * 497 ) ++ NEW metal3 ( 4493 455 ) ( 5291 * ) ++ NEW metal1 ( 4493 497 ) via1_4 ++ NEW metal2 ( 4493 455 ) via2_5 ++ NEW metal1 ( 5291 455 ) via1_4 ++ NEW metal2 ( 5291 455 ) via2_5 ; ++ - w_sel_p1.select_w4 ( sel_buf_w_p1.sel_buf_4 Z ) ( storage_4_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 623 ) ( * 637 ) ++ NEW metal3 ( 5021 595 ) ( * 637 ) ++ NEW metal3 ( 5021 595 ) ( 5291 * ) ++ NEW metal3 ( 4493 637 ) ( 5021 * ) ++ NEW metal1 ( 4493 623 ) via1_4 ++ NEW metal2 ( 4493 637 ) via2_5 ++ NEW metal1 ( 5291 595 ) via1_4 ++ NEW metal2 ( 5291 595 ) via2_5 ; ++ - w_sel_p1.select_w5 ( sel_buf_w_p1.sel_buf_5 Z ) ( storage_5_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 777 ) ( * 791 ) ++ NEW metal3 ( 5021 791 ) ( * 805 ) ++ NEW metal3 ( 5021 805 ) ( 5291 * ) ++ NEW metal3 ( 4493 791 ) ( 5021 * ) ++ NEW metal1 ( 4493 777 ) via1_4 ++ NEW metal2 ( 4493 791 ) via2_5 ++ NEW metal1 ( 5291 805 ) via1_4 ++ NEW metal2 ( 5291 805 ) via2_5 ; ++ - w_sel_p1.select_w6 ( sel_buf_w_p1.sel_buf_6 Z ) ( storage_6_0_0.gcand1 A1 ) + USE SIGNAL ++ + ROUTED metal2 ( 4493 903 ) ( * 973 ) ++ NEW metal3 ( 4909 959 ) ( 5291 * ) ++ NEW metal3 ( 4909 959 ) ( * 973 ) ++ NEW metal3 ( 4493 973 ) ( 4909 * ) ++ NEW metal1 ( 4493 903 ) via1_4 ++ NEW metal2 ( 4493 973 ) via2_5 ++ NEW metal1 ( 5291 959 ) via1_7 ++ NEW metal2 ( 5291 959 ) via2_5 ; ++ - we0[0] ( PIN we0[0] ) ( storage_6_0_0.gcand0 A2 ) ( storage_5_0_0.gcand0 A2 ) ( storage_4_0_0.gcand0 A2 ) ( storage_3_0_0.gcand0 A2 ) ( storage_2_0_0.gcand0 A2 ) ( storage_1_0_0.gcand0 A2 ) ++ ( storage_0_0_0.gcand0 A2 ) + USE SIGNAL ++ + ROUTED metal3 ( 4433 903 ) ( 4436 * ) ++ NEW metal4 ( 4433 903 ) ( * 1113 0 ) ++ NEW metal2 ( 4436 777 ) ( * 903 ) ++ NEW metal2 ( 4436 623 ) ( * 777 ) ++ NEW metal2 ( 4436 497 ) ( * 623 ) ++ NEW metal2 ( 4436 343 ) ( * 497 ) ++ NEW metal2 ( 4436 217 ) ( * 343 ) ++ NEW metal2 ( 4436 63 ) ( * 217 ) ++ NEW metal1 ( 4436 903 ) via1_4 ++ NEW metal2 ( 4436 903 ) via2_5 ++ NEW metal3 ( 4433 903 ) via3_2 ++ NEW metal1 ( 4436 777 ) via1_4 ++ NEW metal1 ( 4436 623 ) via1_4 ++ NEW metal1 ( 4436 497 ) via1_4 ++ NEW metal1 ( 4436 343 ) via1_4 ++ NEW metal1 ( 4436 217 ) via1_4 ++ NEW metal1 ( 4436 63 ) via1_4 ; ++ - we1[0] ( PIN we1[0] ) ( storage_6_0_0.gcand1 A2 ) ( storage_5_0_0.gcand1 A2 ) ( storage_4_0_0.gcand1 A2 ) ( storage_3_0_0.gcand1 A2 ) ( storage_2_0_0.gcand1 A2 ) ( storage_1_0_0.gcand1 A2 ) ++ ( storage_0_0_0.gcand1 A2 ) + USE SIGNAL ++ + ROUTED metal2 ( 4512 903 ) ( * 917 ) ++ NEW metal3 ( 4512 917 ) ( 4545 * ) ++ NEW metal4 ( 4545 917 ) ( * 1113 0 ) ++ NEW metal2 ( 4512 777 ) ( 4531 * ) ++ NEW metal2 ( 4531 777 ) ( * 903 ) ++ NEW metal2 ( 4512 903 ) ( 4531 * ) ++ NEW metal2 ( 4512 623 ) ( * 777 ) ++ NEW metal2 ( 4512 497 ) ( 4531 * ) ++ NEW metal2 ( 4531 497 ) ( * 623 ) ++ NEW metal2 ( 4512 623 ) ( 4531 * ) ++ NEW metal2 ( 4512 343 ) ( * 497 ) ++ NEW metal2 ( 4512 217 ) ( 4531 * ) ++ NEW metal2 ( 4531 217 ) ( * 343 ) ++ NEW metal2 ( 4512 343 ) ( 4531 * ) ++ NEW metal2 ( 4512 63 ) ( * 217 ) ++ NEW metal1 ( 4512 903 ) via1_4 ++ NEW metal2 ( 4512 917 ) via2_5 ++ NEW metal3 ( 4545 917 ) via3_2 ++ NEW metal1 ( 4512 777 ) via1_4 ++ NEW metal1 ( 4512 623 ) via1_4 ++ NEW metal1 ( 4512 497 ) via1_4 ++ NEW metal1 ( 4512 343 ) via1_4 ++ NEW metal1 ( 4512 217 ) via1_4 ++ NEW metal1 ( 4512 63 ) via1_4 ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_7x7_1r2w_nangate45.lefok b/src/ram/test/make_7x7_1r2w_nangate45.lefok +new file mode 100644 +index 0000000000..ca39431cc7 +--- /dev/null ++++ b/src/ram/test/make_7x7_1r2w_nangate45.lefok +@@ -0,0 +1,345 @@ ++VERSION 5.8 ; ++BUSBITCHARS "[]" ; ++DIVIDERCHAR "/" ; ++UNITS ++ DATABASE MICRONS 2000 ; ++END UNITS ++ ++MACRO RAM7x7 ++ FOREIGN RAM7x7 0 0 ; ++ CLASS BLOCK ; ++ SIZE 57.57 BY 11.2 ; ++ PIN clk ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 48.745 11.06 48.885 11.2 ; ++ END ++ END clk ++ PIN we0[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 44.265 11.06 44.405 11.2 ; ++ END ++ END we0[0] ++ PIN we1[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 45.385 11.06 45.525 11.2 ; ++ END ++ END we1[0] ++ PIN addr_w0[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 2.275 57.57 2.345 ; ++ END ++ END addr_w0[0] ++ PIN addr_w0[1] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 3.395 57.57 3.465 ; ++ END ++ END addr_w0[1] ++ PIN addr_w0[2] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 0.595 57.57 0.665 ; ++ END ++ END addr_w0[2] ++ PIN addr_w1[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 2.555 57.57 2.625 ; ++ END ++ END addr_w1[0] ++ PIN addr_w1[1] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 3.675 57.57 3.745 ; ++ END ++ END addr_w1[1] ++ PIN addr_w1[2] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 2.835 57.57 2.905 ; ++ END ++ END addr_w1[2] ++ PIN addr_r0[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 3.115 57.57 3.185 ; ++ END ++ END addr_r0[0] ++ PIN addr_r0[1] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 3.955 57.57 4.025 ; ++ END ++ END addr_r0[1] ++ PIN addr_r0[2] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal3 ; ++ RECT 57.5 0.875 57.57 0.945 ; ++ END ++ END addr_r0[2] ++ PIN D0[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 0.025 11.06 0.165 11.2 ; ++ END ++ END D0[0] ++ PIN D1[0] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 0.585 11.06 0.725 11.2 ; ++ END ++ END D1[0] ++ PIN Q[0] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 3.385 11.06 3.525 11.2 ; ++ END ++ END Q[0] ++ PIN D0[1] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 6.745 11.06 6.885 11.2 ; ++ END ++ END D0[1] ++ PIN D1[1] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 7.305 11.06 7.445 11.2 ; ++ END ++ END D1[1] ++ PIN Q[1] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 9.545 11.06 9.685 11.2 ; ++ END ++ END Q[1] ++ PIN D0[2] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 12.905 11.06 13.045 11.2 ; ++ END ++ END D0[2] ++ PIN D1[2] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 14.025 11.06 14.165 11.2 ; ++ END ++ END D1[2] ++ PIN Q[2] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 15.705 11.06 15.845 11.2 ; ++ END ++ END Q[2] ++ PIN D0[3] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 19.065 11.06 19.205 11.2 ; ++ END ++ END D0[3] ++ PIN D1[3] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 19.625 11.06 19.765 11.2 ; ++ END ++ END D1[3] ++ PIN Q[3] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 21.865 11.06 22.005 11.2 ; ++ END ++ END Q[3] ++ PIN D0[4] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 25.225 11.06 25.365 11.2 ; ++ END ++ END D0[4] ++ PIN D1[4] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 25.785 11.06 25.925 11.2 ; ++ END ++ END D1[4] ++ PIN Q[4] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 28.585 11.06 28.725 11.2 ; ++ END ++ END Q[4] ++ PIN D0[5] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 31.945 11.06 32.085 11.2 ; ++ END ++ END D0[5] ++ PIN D1[5] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 32.505 11.06 32.645 11.2 ; ++ END ++ END D1[5] ++ PIN Q[5] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 34.745 11.06 34.885 11.2 ; ++ END ++ END Q[5] ++ PIN D0[6] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 38.105 11.06 38.245 11.2 ; ++ END ++ END D0[6] ++ PIN D1[6] ++ DIRECTION INPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 38.665 11.06 38.805 11.2 ; ++ END ++ END D1[6] ++ PIN Q[6] ++ DIRECTION OUTPUT ; ++ USE SIGNAL ; ++ PORT ++ LAYER metal4 ; ++ RECT 40.905 11.06 41.045 11.2 ; ++ END ++ END Q[6] ++ PIN VDD ++ DIRECTION INOUT ; ++ USE POWER ; ++ PORT ++ LAYER metal4 ; ++ RECT 49.43 11.06 49.57 11.2 ; ++ RECT 49.43 0 49.57 0.14 ; ++ RECT 40.43 11.06 40.57 11.2 ; ++ RECT 40.43 0 40.57 0.14 ; ++ RECT 31.43 11.06 31.57 11.2 ; ++ RECT 31.43 0 31.57 0.14 ; ++ RECT 22.43 11.06 22.57 11.2 ; ++ RECT 22.43 0 22.57 0.14 ; ++ RECT 13.43 11.06 13.57 11.2 ; ++ RECT 13.43 0 13.57 0.14 ; ++ RECT 4.43 11.06 4.57 11.2 ; ++ RECT 4.43 0 4.57 0.14 ; ++ LAYER metal1 ; ++ RECT 57.5 9.76 57.57 9.84 ; ++ RECT 0 9.76 0.07 9.84 ; ++ RECT 57.5 6.96 57.57 7.04 ; ++ RECT 0 6.96 0.07 7.04 ; ++ RECT 57.5 4.16 57.57 4.24 ; ++ RECT 0 4.16 0.07 4.24 ; ++ RECT 57.5 1.36 57.57 1.44 ; ++ RECT 0 1.36 0.07 1.44 ; ++ END ++ END VDD ++ PIN VSS ++ DIRECTION INOUT ; ++ USE GROUND ; ++ PORT ++ LAYER metal4 ; ++ RECT 53.93 11.06 54.07 11.2 ; ++ RECT 53.93 0 54.07 0.14 ; ++ RECT 44.93 11.06 45.07 11.2 ; ++ RECT 44.93 0 45.07 0.14 ; ++ RECT 35.93 11.06 36.07 11.2 ; ++ RECT 35.93 0 36.07 0.14 ; ++ RECT 26.93 11.06 27.07 11.2 ; ++ RECT 26.93 0 27.07 0.14 ; ++ RECT 17.93 11.06 18.07 11.2 ; ++ RECT 17.93 0 18.07 0.14 ; ++ RECT 8.93 11.06 9.07 11.2 ; ++ RECT 8.93 0 9.07 0.14 ; ++ LAYER metal1 ; ++ RECT 57.5 11.16 57.57 11.24 ; ++ RECT 0 11.16 0.07 11.24 ; ++ RECT 57.5 8.36 57.57 8.44 ; ++ RECT 0 8.36 0.07 8.44 ; ++ RECT 57.5 5.56 57.57 5.64 ; ++ RECT 0 5.56 0.07 5.64 ; ++ RECT 57.5 2.76 57.57 2.84 ; ++ RECT 0 2.76 0.07 2.84 ; ++ RECT 57.5 -0.04 57.57 0.04 ; ++ RECT 0 -0.04 0.07 0.04 ; ++ END ++ END VSS ++ OBS ++ LAYER metal1 ; ++ RECT 0 -0.07 57.57 11.27 ; ++ LAYER metal2 ; ++ RECT 0 -0.07 57.57 11.27 ; ++ LAYER metal3 ; ++ RECT 0 -0.07 57.57 11.27 ; ++ LAYER metal4 ; ++ RECT 0 -0.07 57.57 11.27 ; ++ END ++END RAM7x7 ++END LIBRARY +diff --git a/src/ram/test/make_7x7_1r2w_nangate45.tcl b/src/ram/test/make_7x7_1r2w_nangate45.tcl +new file mode 100644 +index 0000000000..2a8203432e +--- /dev/null ++++ b/src/ram/test/make_7x7_1r2w_nangate45.tcl +@@ -0,0 +1,36 @@ ++source "helpers.tcl" ++ ++set_thread_count [expr [cpu_count] / 4] ++ ++read_liberty Nangate45/Nangate45_typ.lib ++ ++read_lef Nangate45/Nangate45_tech.lef ++read_lef Nangate45/Nangate45.lef ++ ++set behavioral_file [make_result_file make_7x7_1r2w_nangate45_behavioral.v] ++ ++generate_ram \ ++ -mask_size 7 \ ++ -word_size 7 \ ++ -num_words 7 \ ++ -r_ports 1 \ ++ -w_ports 2 \ ++ -storage_cell DFF_X1 \ ++ -routing_layer {metal1 0.08} \ ++ -ver_layer {metal4 0.14 9} \ ++ -hor_layer {metal3 0.08 8} \ ++ -filler_cells {FILLCELL_X1 FILLCELL_X2 FILLCELL_X4 FILLCELL_X8} \ ++ -tapcell TAPCELL_X1 \ ++ -max_tap_dist 10 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set lef_file [make_result_file make_7x7_1r2w_nangate45.lef] ++write_abstract_lef -bloat_occupied_layers $lef_file ++diff_files make_7x7_1r2w_nangate45.lefok $lef_file ++ ++set def_file [make_result_file make_7x7_1r2w_nangate45.def] ++write_def $def_file ++diff_files make_7x7_1r2w_nangate45.defok $def_file ++ ++diff_files make_7x7_1r2w_nangate45_behavioral.vok $behavioral_file ++puts "pass" +diff --git a/src/ram/test/make_7x7_1r2w_nangate45_behavioral.vok b/src/ram/test/make_7x7_1r2w_nangate45_behavioral.vok +new file mode 100644 +index 0000000000..99a9a13805 +--- /dev/null ++++ b/src/ram/test/make_7x7_1r2w_nangate45_behavioral.vok +@@ -0,0 +1,45 @@ ++module RAM7x7 ( ++ clk, ++ D0, ++ D1, ++ Q, ++ addr_w0, ++ addr_w1, ++ addr_r0, ++ we0, ++ we1 ++); ++ input clk; ++ input [6:0] D0; ++ input [6:0] D1; ++ output reg [6:0] Q; ++ input [2:0] addr_w0; ++ input [2:0] addr_w1; ++ input [2:0] addr_r0; ++ input [0:0] we0; ++ input [0:0] we1; ++ ++ // memory array declaration ++ reg [6:0] mem[0:6]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we0[i]) begin ++ mem[addr_w0][i*7 +:7] <= D0[i*7 +:7]; ++ end ++ end ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we1[i]) begin ++ mem[addr_w1][i*7 +:7] <= D1[i*7 +:7]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q = mem[addr_r0]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index be787532f2..d6ce26bfc6 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -5,5 +5,6 @@ record_tests { + make_8x8_mux4_sky130 + make_8x8_2r1w_sky130 + make_7x7_2r1w_nangate45 ++ make_7x7_1r2w_nangate45 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index e7d64d6fb..7ee28d607 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -171,6 +171,7 @@ test_suite( "@openroad//src/ram/test:generate_regfile_reset_high_asap7-tcl_test", "@openroad//src/ram/test:generate_regfile_sv_ports_asap7-tcl_test", "@openroad//src/ram/test:generate_regfile_write_priority_asap7-tcl_test", + "@openroad//src/ram/test:make_7x7_1r2w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_2r1w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 4c4b21af6..66a4058c5 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -110,3 +110,76 @@ sed -e 's/^module regfile(/module regfile_gen(/' -e '/^(\\* blackbox \\*)$$/,$$d ), ] ] + +# generate_ram with two write ports (OpenROAD patch 0011): its netlist +# beside its own behavioral model on Nangate45, whose tristate buffers +# make the read bitlines, under random writes on both ports, a quarter +# of them to the same word, the last port winning. +stdcell_verilog( + name = "nangate45_stdcell", + lefs = ["@orfs//flow:platforms/nangate45/lef/NangateOpenCellLibrary.macro.mod.lef"], + libs = ["@orfs//flow:platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib"], +) + +genrule( + name = "ram_2w_v", + srcs = [ + "@orfs//flow:platforms/nangate45/lef/NangateOpenCellLibrary.tech.lef", + "@orfs//flow:platforms/nangate45/lef/NangateOpenCellLibrary.macro.mod.lef", + "@orfs//flow:platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib", + ], + outs = [ + "ram_2w_gen.v", + "ram_2w_model.v", + ], + cmd = """ +cat > $(@D)/ram_2w.tcl < $(@D)/ram_2w.log 2>&1 || { cat $(@D)/ram_2w.log; exit 1; } +# write_verilog needs the network linked to the block, as reading it back +# does +cat > $(@D)/ram_2w_v.tcl <> $(@D)/ram_2w.log 2>&1 || { cat $(@D)/ram_2w.log; exit 1; } +sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/ram_2w.v > $(location ram_2w_gen.v) +""", + tools = ["@openroad"], +) + +verilog_library( + name = "tb_ram_2w_rtl", + srcs = [ + "tb_ram_2w.v", + ":nangate45_stdcell.v", + ":nangate45_stdcell_empty.v", + ":ram_2w_gen.v", + ":ram_2w_model.v", + ], +) + +verilator_cc_library( + name = "tb_ram_2w", + module = ":tb_ram_2w_rtl", + module_top = "tb_ram_2w", + trace_mode = "none", + vopts = [ + "-Wno-fatal", + "--x-initial", + "0", + ], +) + +cc_test( + name = "ram_2w_sim_test", + size = "small", + srcs = ["tb_ram_2w.cc"], + deps = [":tb_ram_2w"], +) diff --git a/test/regfile/sim/tb_ram_2w.cc b/test/regfile/sim/tb_ram_2w.cc new file mode 100644 index 000000000..d693d5317 --- /dev/null +++ b/test/regfile/sim/tb_ram_2w.cc @@ -0,0 +1,48 @@ +// Random writes on both ports of generate_ram's two-write-port RAM, a +// quarter of them to the same word in the same cycle, and a read every +// cycle compared between the netlist and the behavioral model. Every +// word is written once first, unchecked: an unwritten word reads each +// side's power-up state. +#include +#include +#include + +#include "Vtb_ram_2w.h" + +int main() { + Vtb_ram_2w tb; + std::mt19937 rng(1); + int bad = 0; + int cycle = 0; + auto step = [&](bool check, bool we0, int a0, int d0, bool we1, int a1, + int d1, int ra) { + tb.clk = 0; + tb.we0 = we0; + tb.addr_w0 = a0; + tb.D0 = d0; + tb.we1 = we1; + tb.addr_w1 = a1; + tb.D1 = d1; + tb.addr_r0 = ra; + tb.eval(); + if (check && tb.Q_model != tb.Q_gen) { + std::printf("cycle %d: read %d: model %02x, generated %02x\n", cycle, + ra, tb.Q_model, tb.Q_gen); + ++bad; + } + tb.clk = 1; + tb.eval(); + ++cycle; + }; + for (int w = 0; w < 8; ++w) { + step(false, true, w, rng() & 0xff, false, 0, 0, w); + } + for (int i = 0; i < 20000 && bad < 10; ++i) { + const int a0 = rng() % 8; + const int a1 = rng() % 4 == 0 ? a0 : rng() % 8; + step(true, rng() % 2, a0, rng() & 0xff, rng() % 2, a1, rng() & 0xff, + rng() % 8); + } + std::printf("%d cycles, %d mismatches\n", cycle, bad); + return bad == 0 ? 0 : 1; +} diff --git a/test/regfile/sim/tb_ram_2w.v b/test/regfile/sim/tb_ram_2w.v new file mode 100644 index 000000000..a44d1698f --- /dev/null +++ b/test/regfile/sim/tb_ram_2w.v @@ -0,0 +1,23 @@ +// generate_ram with two write ports and one read port: its behavioral +// model (RAM8x8) and its netlist (RAM8x8_gen) on the same inputs. +module tb_ram_2w ( + input clk, + input [7:0] D0, + input [7:0] D1, + input [2:0] addr_w0, + input [2:0] addr_w1, + input [2:0] addr_r0, + input we0, + input we1, + output [7:0] Q_model, + output [7:0] Q_gen +); + RAM8x8 model ( + .clk(clk), .D0(D0), .D1(D1), .Q(Q_model), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1) + ); + RAM8x8_gen gen ( + .clk(clk), .D0(D0), .D1(D1), .Q(Q_gen), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1) + ); +endmodule From 761d2ffc147788e62558b0182273008b472f1ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 08:19:43 +0200 Subject: [PATCH 11/26] ram: generate_ram reads through AND-OR trees without tristates (patch 0012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The second generate_regfile feature carried onto generate_ram, on 0011. generate_ram's read path is a tristate bitline per bit, so a library without a tristate cell, asap7, could not generate (RAM-0010). -read_style and_or reads through a tree per bit column: an AOI22 over each pair of rows, then NAND2 and NOR2 by turns, each node in a row of the span it covers. It is the default where there is no tristate cell, and can be asked for where there is one. A flop whose output is its data inverted is taken on that path, an inverter at each root undoing it. buildPortMap reckoned polarity from the state variable alone and took asap7's DFFHQNx1, whose state holds !D, for a true output; it now counts next_state too. NAND2 and NOR2 are found by truth table, as asap7 writes NAND2 as (!A) + (!B). Tests: make_8x8_2r1w_and_or_asap7, golden DEF and behavioral model in generate_ram's format; test/regfile/sim simulates generate_ram's 8 x 8 two-write RAM against its behavioral model in three shapes, Nangate45's tristates, Nangate45's trees asked for and asap7's: 20 008 cycles each, no mismatch. generate_ram's existing tests are unchanged. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 4 + patches/0012-openroad-ram-and-or-read.patch | 1568 +++++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 144 +- 4 files changed, 1664 insertions(+), 53 deletions(-) create mode 100644 patches/0012-openroad-ram-and-or-read.patch diff --git a/MODULE.bazel b/MODULE.bazel index a7413e922..99dd2d08f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -132,6 +132,10 @@ archive_override( # The first generate_regfile feature carried onto generate_ram # (OpenROAD #11669); not upstreamed. "//patches:0011-openroad-ram-multiple-write-ports.patch", + # 0012: generate_ram reads through AND-OR trees where the library + # has no tristate cell (asap7), or when asked; a QN-only storage + # flop taken there. On 0011 (OpenROAD #11669); not upstreamed. + "//patches:0012-openroad-ram-and-or-read.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0012-openroad-ram-and-or-read.patch b/patches/0012-openroad-ram-and-or-read.patch new file mode 100644 index 000000000..79c059d92 --- /dev/null +++ b/patches/0012-openroad-ram-and-or-read.patch @@ -0,0 +1,1568 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram reads through AND-OR trees without tristates + +generate_ram's read path is a tristate bitline per bit, and a library +without a tristate cell (asap7) could not generate at all (RAM-0010). +-read_style and_or reads through a tree per bit column instead: an +AOI22 over each pair of rows, then NAND2 and NOR2 levels by turns, each +node placed in a row of the span it covers, beside its inputs. It is the +default where the library has no tristate cell (RAM-0057 says so), and +can be asked for where it has one; -read_style tristate insists on the +bitlines. + +A storage flop whose output is the data inverted is taken on the +AND-OR path, an inverter at the root of each tree undoing it; the +tristate path refuses it (RAM-0058). buildPortMap now reckons a flop's +output polarity from both the state variable a pin reads and its +next_state: asap7's DFFHQNx1 stores !D in IQN and outputs IQN on QN, +which it took for a true output. Cells with next_state "D" are as +before. NAND2 and NOR2 are found by truth table (asap7 writes NAND2 as +(!A) + (!B)), through the evaluator findMaster4 used, now shared. + +The second of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 008107da2d..f7981d19fc 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -43,6 +43,7 @@ generate_ram [-mask_size bits] + [-column_mux_ratio ratio] + [-storage_cell name] + [-tristate_cell name] ++ [-read_style tristate|and_or] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -68,6 +69,7 @@ generate_ram [-mask_size bits] + | `-column_mux_ratio` | Number of words sharing a physical column. Must be `1`, `2`, or `4`. The number of words must be divisible by the column mux ratio. Default: `1` (no column muxing). | + | `-storage_cell` | Name of the master to use for the storage device (i.e. a flip-flop). Must be positive-edge triggered. Default: auto-select from the loaded cell library. | + | `-tristate_cell` | Name of the master to use for the tristate device (i.e. a tristate inverter). It is currently assumed that the device is inverting. Default: auto-select from the loaded cell library. | ++| `-read_style` | The read path: `tristate`, a tristate bitline per bit, or `and_or`, a tree per bit column of an AOI22 over each pair of rows and NAND2 and NOR2 levels above, for a library without a tristate cell. `and_or` also takes a storage flop whose only output is inverted (QN). Default: `tristate` where the library has a tristate cell, `and_or` where it has none. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 3b9844cbae..db535732f0 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -108,7 +109,8 @@ class RamGen + odb::dbMaster* tristate_cell, + odb::dbMaster* inv_cell, + odb::dbMaster* tapcell, +- int max_tap_dist); ++ int max_tap_dist, ++ const std::string& read_style = ""); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -135,7 +137,33 @@ class RamGen + + private: + void findMasters(); +- std::map buildPortMap(odb::dbMaster*); ++ // `inverted`, if given, is set when a flop's only data output is its ++ // inverted one (QN), which then stands as DataOut. ++ std::map buildPortMap(odb::dbMaster*, ++ bool* inverted = nullptr); ++ // The AND-OR read path: each read port's bitline a tree over the rows ++ // of a bit column, planned before the rows are built (planReadTree) and ++ // placed row by row with the bits (treeNodes_). ++ struct TreeNode ++ { ++ odb::dbMaster* master; ++ std::string prefix; ++ std::string name; ++ std::vector> conns; ++ }; ++ struct TreeEnd ++ { ++ odb::dbNet* net; ++ bool inverted; // the net is the complement of the OR of the terms ++ }; ++ TreeEnd planReadTree(const std::string& prefix, ++ int word_idx, ++ int bit, ++ int lo, ++ int hi, ++ const std::vector& selects, ++ odb::dbNet* out); ++ bool treeInverted(int lo, int hi) const; + // The smallest cell `match` accepts; none is an error unless not + // `required`, then nullptr. + odb::dbMaster* findMaster(const std::function& match, +@@ -161,7 +189,8 @@ class RamGen + odb::dbNet* clock, + std::vector& select, + odb::dbNet* data_input, +- std::vector& data_output); ++ std::vector& data_output, ++ odb::dbNet* storage_net = nullptr); + void makeSlice(int slice_idx, + int mask_size, + int row_idx, +@@ -246,6 +275,9 @@ class RamGen + // enables' OR + odb::dbMaster* ao22_cell_{nullptr}; + odb::dbMaster* or2_cell_{nullptr}; ++ // the AND-OR read path's tree ++ odb::dbMaster* nand2_cell_{nullptr}; ++ odb::dbMaster* nor2_cell_{nullptr}; + odb::dbMaster* latch_cell_{nullptr}; + odb::dbMaster* tapcell_{nullptr}; + +@@ -260,6 +292,8 @@ class RamGen + std::map buffer_ports_; + std::map latch_ports_; + std::map or2_ports_; ++ std::map nand2_ports_; ++ std::map nor2_ports_; + + std::vector> addr_inputs_; + std::vector data_inputs_; // every write port's data +@@ -272,6 +306,15 @@ class RamGen + Grid ram_grid_; + bool use_latch_{false}; + int num_write_{1}; // write and read/write ports ++ // Reads through AND-OR trees instead of tristate bitlines: asked for, ++ // or the library has no tristate cell. ++ bool and_or_read_{false}; ++ std::string read_style_; ++ bool storage_inverted_{false}; // the storage flop's output is QN ++ // per (row, word in the row, bit): the storage net, and the tree ++ // cells placed in that bit's cell ++ std::map, odb::dbNet*> storage_nets_; ++ std::map, std::vector> tree_nodes_; + }; + + } // namespace ram +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 7e97ae2600..463e1f3a86 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -115,11 +115,15 @@ std::unique_ptr RamGen::makeBit(const std::string& prefix, + dbNet* clock, + vector& select, + dbNet* data_input, +- vector& data_output) ++ vector& data_output, ++ dbNet* storage_net) + { + auto bit_cell = std::make_unique(); + +- auto storage_net = makeNet(prefix, "storage"); ++ // the AND-OR read path names the storage net ahead, for its trees ++ if (storage_net == nullptr) { ++ storage_net = makeNet(prefix, "storage"); ++ } + + if (!use_latch_) { + makeInst(bit_cell.get(), +@@ -154,6 +158,106 @@ std::unique_ptr RamGen::makeBit(const std::string& prefix, + return bit_cell; + } + ++// The AND-OR read path: one read port's bitline of one bit column, rows ++// [lo, hi), as a tree: an AOI22 over each pair of rows (a NAND2 over a ++// lone row), then NAND2 and NOR2 levels by turns, each node in the last ++// row of its left half, beside its inputs. Planned before the rows are ++// built; each row's bit cell takes its nodes from tree_nodes_. ++bool RamGen::treeInverted(const int lo, const int hi) const ++{ ++ const int n = hi - lo; ++ if (n <= 2) { ++ return true; // AOI22 or NAND2: the complement of the terms' OR ++ } ++ int half = 1; ++ while (half * 2 < n) { ++ half *= 2; ++ } ++ // the right half is brought to the left's polarity, and the node ++ // (NAND2 of complements, NOR2 of trues) flips it ++ return !treeInverted(lo, lo + half); ++} ++ ++RamGen::TreeEnd RamGen::planReadTree(const std::string& prefix, ++ const int word_idx, ++ const int bit, ++ const int lo, ++ const int hi, ++ const vector& selects, ++ dbNet* out) ++{ ++ auto add = [&](const int row, ++ dbMaster* master, ++ const std::string& name, ++ const vector>& conns) { ++ tree_nodes_[{row, word_idx, bit}].push_back({master, prefix, name, conns}); ++ }; ++ auto q = [&](const int row) { ++ return storage_nets_.at({row, word_idx, bit}); ++ }; ++ auto net = [&](dbNet* given) { ++ return given ? given : makeNet(prefix, fmt::format("t{}_{}", lo, hi)); ++ }; ++ const int n = hi - lo; ++ if (n == 1) { ++ dbNet* y = net(out); ++ add(lo, ++ nand2_cell_, ++ fmt::format("nand_r{}", lo), ++ {{nand2_ports_[{PortRoleType::DataIn, 0}], selects[lo]}, ++ {nand2_ports_[{PortRoleType::DataIn, 1}], q(lo)}, ++ {nand2_ports_[{PortRoleType::DataOut, 0}], y}}); ++ return {y, true}; ++ } ++ if (n == 2) { ++ dbNet* y = net(out); ++ add(lo, ++ aoi22_cell_, ++ fmt::format("aoi_r{}", lo), ++ {{aoi22_in_a1_, selects[lo]}, ++ {aoi22_in_a2_, q(lo)}, ++ {aoi22_in_b1_, selects[lo + 1]}, ++ {aoi22_in_b2_, q(lo + 1)}, ++ {aoi22_out_, y}}); ++ return {y, true}; ++ } ++ int half = 1; ++ while (half * 2 < n) { ++ half *= 2; ++ } ++ const int mid = lo + half; ++ const int host = mid - 1; ++ const TreeEnd a ++ = planReadTree(prefix, word_idx, bit, lo, mid, selects, nullptr); ++ TreeEnd b = planReadTree(prefix, word_idx, bit, mid, hi, selects, nullptr); ++ if (b.inverted != a.inverted) { ++ dbNet* nb = makeNet(prefix, fmt::format("t{}_{}_inv", mid, hi)); ++ add(mid, ++ inv_cell_, ++ fmt::format("inv_r{}_{}", mid, hi), ++ {{inv_ports_[{PortRoleType::DataIn, 0}], b.net}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], nb}}); ++ b = {nb, a.inverted}; ++ } ++ dbNet* y = net(out); ++ if (a.inverted) { ++ add(host, ++ nand2_cell_, ++ fmt::format("nand_r{}_{}", lo, hi), ++ {{nand2_ports_[{PortRoleType::DataIn, 0}], a.net}, ++ {nand2_ports_[{PortRoleType::DataIn, 1}], b.net}, ++ {nand2_ports_[{PortRoleType::DataOut, 0}], y}}); ++ return {y, false}; ++ } ++ add(host, ++ nor2_cell_, ++ fmt::format("nor_r{}_{}", lo, hi), ++ {{nor2_ports_[{PortRoleType::DataIn, 0}], a.net}, ++ {nor2_ports_[{PortRoleType::DataIn, 1}], b.net}, ++ {nor2_ports_[{PortRoleType::DataOut, 0}], y}}); ++ return {y, true}; ++} ++ + // Note: For column_mux_ratio > 1, a single shared select_b net and select_inv + // gate are reused across all words in the same physical row (passed via + // shared_select_b_nets). This avoids creating redundant nets and gates per +@@ -186,7 +290,9 @@ void RamGen::makeSlice(const int slice_idx, + + int r_total = rw_ports + r_ports; + vector select_b_nets(r_total); +- if (column_mux_ratio == 1) { ++ if (and_or_read_) { ++ // the AND-OR trees read the true selects ++ } else if (column_mux_ratio == 1) { + for (int i = 0; i < r_total; ++i) { + select_b_nets[i] = makeNet(prefix, fmt::format("select{}_b", i)); + } +@@ -259,8 +365,21 @@ void RamGen::makeSlice(const int slice_idx, + if (num_write > 1) { + d = makeNet(name, "d"); + } +- auto bit_cell +- = makeBit(name, r_total, gclock_net, select_b_nets, d, outs); ++ const int bit = start_bit_idx + local_bit; ++ auto bit_cell = and_or_read_ ++ ? makeBit(name, ++ 0, ++ gclock_net, ++ select_b_nets, ++ d, ++ outs, ++ storage_nets_.at({row_idx, word_idx, bit})) ++ : makeBit(name, r_total, gclock_net, select_b_nets, d, outs); ++ if (and_or_read_) { ++ for (const auto& node : tree_nodes_[{row_idx, word_idx, bit}]) { ++ makeInst(bit_cell.get(), node.prefix, node.name, node.master, node.conns); ++ } ++ } + if (num_write > 1) { + // the taken port's data: AO22 over pairs of ports, OR2 across pairs + dbNet* acc = nullptr; +@@ -365,7 +484,7 @@ void RamGen::makeSlice(const int slice_idx, + } + + // Make select inverters +- if (create_select_inv) { ++ if (create_select_inv && !and_or_read_) { + for (int i = 0; i < r_total; ++i) { + makeInst(sel_cell.get(), + prefix, +@@ -662,8 +781,13 @@ dbMaster* RamGen::findMaster( + return best; + } + +-std::map RamGen::buildPortMap(dbMaster* master) ++std::map RamGen::buildPortMap(dbMaster* master, ++ bool* inverted) + { ++ if (inverted) { ++ *inverted = false; ++ } ++ std::string inverted_out; // a flop's inverted output (QN) + auto sta_cell = network_->dbToSta(master); + auto liberty = network_->libertyCell(sta_cell); + std::map pin_map; +@@ -711,8 +835,13 @@ std::map RamGen::buildPortMap(dbMaster* master) + auto seq = lib_cell->outputPortSequential(internal_port); + if (seq) { + is_seq_output = true; +- // outputInv() is the negative state variable (IQN) +- is_seq_inverted = (seq->outputInv() == internal_port); ++ // outputInv() is the negative state variable (IQN); a state ++ // that stores the data inverted (next_state "!D", asap7's ++ // DFFHQNx1) inverts it again ++ const bool stores_inverted ++ = seq->data() && seq->data()->op() == sta::FuncExpr::Op::not_; ++ is_seq_inverted ++ = (seq->outputInv() == internal_port) != stores_inverted; + } + } + } +@@ -721,6 +850,8 @@ std::map RamGen::buildPortMap(dbMaster* master) + // only assign if this is the non-inverted output (Q and not Qn) + if (!is_seq_inverted) { + pin_map[{PortRoleType::DataOut, 0}] = lib_port->name(); ++ } else { ++ inverted_out = lib_port->name(); + } + } else { + // non-sequential cell (AND2, INV etc) assign as DataOut +@@ -731,6 +862,14 @@ std::map RamGen::buildPortMap(dbMaster* master) + } + } + ++ // A flop whose only data output is QN: QN stands as DataOut, for a ++ // caller that says it can take the inversion. ++ if (inverted && !inverted_out.empty() ++ && pin_map.find({PortRoleType::DataOut, 0}) == pin_map.end()) { ++ pin_map[{PortRoleType::DataOut, 0}] = inverted_out; ++ *inverted = true; ++ } ++ + // second pass for to assign tristate enable correct role + // first pass can not classify without a dedicated tristate flag + if (!tri_enable_name.empty()) { +@@ -781,6 +920,75 @@ std::map RamGen::buildPortMap(dbMaster* master) + return pin_map; + } + ++// Evaluates a liberty function expression given its input ports' values. ++static bool evalFunc(const sta::FuncExpr* expr, ++ const std::vector& ports, ++ const std::vector& vals) ++{ ++ if (!expr) { ++ return false; ++ } ++ switch (expr->op()) { ++ case sta::FuncExpr::Op::port: { ++ // look up this port's value in the input vector ++ auto p = expr->port(); ++ for (int i = 0; i < (int) ports.size(); ++i) { ++ if (ports[i] == p) { ++ return vals[i]; ++ } ++ } ++ return false; ++ } ++ case sta::FuncExpr::Op::not_: ++ return !evalFunc(expr->left(), ports, vals); ++ case sta::FuncExpr::Op::and_: ++ return evalFunc(expr->left(), ports, vals) ++ && evalFunc(expr->right(), ports, vals); ++ case sta::FuncExpr::Op::or_: ++ return evalFunc(expr->left(), ports, vals) ++ || evalFunc(expr->right(), ports, vals); ++ case sta::FuncExpr::Op::xor_: ++ return evalFunc(expr->left(), ports, vals) ++ != evalFunc(expr->right(), ports, vals); ++ case sta::FuncExpr::Op::one: ++ return true; ++ case sta::FuncExpr::Op::zero: ++ return false; ++ default: ++ return false; ++ } ++} ++ ++// The truth table of a two-input single-output cell's output, bit k its ++// value for inputs k in binary; -1 for any other cell. Symmetric ++// functions only (AND, OR, NAND, NOR), so the inputs' order is moot. ++static int twoInputTable(sta::LibertyPort* out) ++{ ++ auto func = out->function(); ++ if (!func || !out->direction()->isOutput()) { ++ return -1; ++ } ++ std::vector inputs; ++ std::unique_ptr port_iter( ++ out->libertyCell()->portIterator()); ++ while (port_iter->hasNext()) { ++ auto p = static_cast(port_iter->next()); ++ if (p->direction()->isInput()) { ++ inputs.push_back(p->libertyPort()); ++ } ++ } ++ if (inputs.size() != 2) { ++ return -1; ++ } ++ int table = 0; ++ for (int k = 0; k < 4; ++k) { ++ if (evalFunc(func, inputs, {(k & 1) != 0, (k & 2) != 0})) { ++ table |= 1 << k; ++ } ++ } ++ return table; ++} ++ + void RamGen::findMasters() + { + if (!inv_cell_) { +@@ -792,18 +1000,30 @@ void RamGen::findMasters() + } + inv_ports_ = buildPortMap(inv_cell_); + +- if (!tristate_cell_) { +- tristate_cell_ = findMaster( +- [](sta::LibertyPort* port) { +- if (!port->direction()->isTristate()) { +- return false; +- } +- auto function = port->function(); +- return function->op() != sta::FuncExpr::Op::not_; +- }, +- "tristate"); ++ // The read path: tristate bitlines where the library has a tristate ++ // cell, AND-OR trees where it has none, or as -read_style says. ++ if (read_style_ == "and_or") { ++ and_or_read_ = true; ++ } else { ++ if (!tristate_cell_) { ++ tristate_cell_ = findMaster( ++ [](sta::LibertyPort* port) { ++ if (!port->direction()->isTristate()) { ++ return false; ++ } ++ auto function = port->function(); ++ return function->op() != sta::FuncExpr::Op::not_; ++ }, ++ "tristate", ++ /*required=*/read_style_ == "tristate"); ++ } ++ if (tristate_cell_) { ++ tristate_ports_ = buildPortMap(tristate_cell_); ++ } else { ++ and_or_read_ = true; ++ logger_->info(RAM, 57, "No tristate cell: reads through AND-OR trees."); ++ } + } +- tristate_ports_ = buildPortMap(tristate_cell_); + + if (!and2_cell_) { + and2_cell_ = findMaster( +@@ -845,7 +1065,18 @@ void RamGen::findMasters() + }, + "storage"); + } +- storage_ports_ = buildPortMap(storage_cell_); ++ // the AND-OR read path takes a flop whose only output is QN; its ++ // trees undo the inversion ++ storage_ports_ = buildPortMap(storage_cell_, ++ and_or_read_ ? &storage_inverted_ : nullptr); ++ if (storage_ports_.find({PortRoleType::DataOut, 0}) ++ == storage_ports_.end()) { ++ logger_->error(RAM, ++ 58, ++ "Storage cell {} has no non-inverted output; use " ++ "-read_style and_or.", ++ storage_cell_->getName()); ++ } + } + + if (!clock_gate_cell_) { +@@ -913,6 +1144,23 @@ void RamGen::findMasters() + aoi22_in_b2_ = in[3]; + } + ++ // The AND-OR read path's tree: NAND2 and NOR2 levels over AOI22 leaves. ++ if (and_or_read_) { ++ // by truth table: asap7 writes its NAND2 as (!A) + (!B) ++ if (!nand2_cell_) { ++ nand2_cell_ = findMaster( ++ [](sta::LibertyPort* port) { return twoInputTable(port) == 0x7; }, ++ "nand2"); ++ } ++ nand2_ports_ = buildPortMap(nand2_cell_); ++ if (!nor2_cell_) { ++ nor2_cell_ = findMaster( ++ [](sta::LibertyPort* port) { return twoInputTable(port) == 0x1; }, ++ "nor2"); ++ } ++ nor2_ports_ = buildPortMap(nor2_cell_); ++ } ++ + // More than one write port: the write data mux, an AO22 per pair of + // ports, and an OR2 for the write enables and across pairs. + if (num_write_ > 1) { +@@ -947,56 +1195,12 @@ dbMaster* RamGen::findMaster4(const uint16_t table, + // for 4 inputs ordered (A1,A2,B1,B2) mapped to bits (0,1,2,3), + // bit k of the table = output when inputs = k in binary. + +- // recursively evaluate a liberty function expression given input port +- // values +- std::function&, +- const std::vector&)> +- evalFunc; +- +- evalFunc = [&evalFunc](const sta::FuncExpr* expr, +- const std::vector& ports, +- const std::vector& vals) -> bool { +- if (!expr) { +- return false; +- } +- switch (expr->op()) { +- case sta::FuncExpr::Op::port: { +- // look up this port's value in the input vector +- auto p = expr->port(); +- for (int i = 0; i < (int) ports.size(); ++i) { +- if (ports[i] == p) { +- return vals[i]; +- } +- } +- return false; +- } +- case sta::FuncExpr::Op::not_: +- return !evalFunc(expr->left(), ports, vals); +- case sta::FuncExpr::Op::and_: +- return evalFunc(expr->left(), ports, vals) +- && evalFunc(expr->right(), ports, vals); +- case sta::FuncExpr::Op::or_: +- return evalFunc(expr->left(), ports, vals) +- || evalFunc(expr->right(), ports, vals); +- case sta::FuncExpr::Op::xor_: +- return evalFunc(expr->left(), ports, vals) +- != evalFunc(expr->right(), ports, vals); +- case sta::FuncExpr::Op::one: +- return true; +- case sta::FuncExpr::Op::zero: +- return false; +- default: +- return false; +- } +- }; +- + // compute 16-entry truth table for a function given 4 ordered input ports. + // each bit k of the result = output when inputs = k in binary. (i.e. k= 2 = + // 10) + auto computeTable = +- [&evalFunc](const sta::FuncExpr* func, +- const std::vector& inputs) -> uint16_t { ++ [](const sta::FuncExpr* func, ++ const std::vector& inputs) -> uint16_t { + uint16_t table = 0; + for (int k = 0; k < 16; ++k) { + std::vector vals(4); +@@ -1320,7 +1524,8 @@ void RamGen::generate(const int mask_size, + dbMaster* tristate_cell, + dbMaster* inv_cell, + dbMaster* tapcell, +- int max_tap_dist) ++ int max_tap_dist, ++ const std::string& read_style) + { + if (num_words / column_mux_ratio == 1) { + logger_->error(RAM, 42, "1-row RAMs are not supported."); +@@ -1367,6 +1572,11 @@ void RamGen::generate(const int mask_size, + + use_latch_ = use_latch; + num_write_ = rw_ports + w_ports; ++ read_style_ = read_style; ++ and_or_read_ = false; ++ storage_inverted_ = false; ++ storage_nets_.clear(); ++ tree_nodes_.clear(); + storage_cell_ = storage_cell; + tristate_cell_ = tristate_cell; + inv_cell_ = inv_cell; +@@ -1377,6 +1587,8 @@ void RamGen::generate(const int mask_size, + aoi22_cell_ = nullptr; + ao22_cell_ = nullptr; + or2_cell_ = nullptr; ++ nand2_cell_ = nullptr; ++ nor2_cell_ = nullptr; + latch_cell_ = nullptr; + + if (use_latch_ && storage_cell_) { +@@ -1622,6 +1834,49 @@ void RamGen::generate(const int mask_size, + // gate — all other word_idx reuse the existing net, reducing cell count + // and horizontal routing congestion in storage rows. + ++ // The AND-OR read path: every storage net named ahead, and every ++ // bitline's tree planned, so each row's bit cells take their nodes. ++ // Where the storage flop's output is QN, or the tree's root is ++ // inverted, but not both, an inverter at the bottom row puts it right. ++ if (and_or_read_) { ++ for (int row = 0; row < num_rows; ++row) { ++ for (int w = 0; w < column_mux_ratio; ++w) { ++ for (int bit = 0; bit < word_size; ++bit) { ++ const std::string prefix = fmt::format( ++ "storage_{}_{}_{}", row, w, (bit / mask_size) * mask_size); ++ storage_nets_[{row, w, bit}] = makeNet( ++ fmt::format("{}.bit{}", prefix, bit), "storage"); ++ } ++ } ++ } ++ const bool flip = treeInverted(0, num_rows) != storage_inverted_; ++ for (int w = 0; w < column_mux_ratio; ++w) { ++ for (int port = 0; port < r_total; ++port) { ++ for (int bit = 0; bit < word_size; ++bit) { ++ const std::string prefix ++ = fmt::format("read_w{}_p{}_b{}", w, port, bit); ++ dbNet* out = word_q_nets[w][port][bit]; ++ const TreeEnd root ++ = planReadTree(prefix, ++ w, ++ bit, ++ 0, ++ num_rows, ++ read_select_nets[port], ++ flip ? nullptr : out); ++ if (flip) { ++ tree_nodes_[{num_rows - 1, w, bit}].push_back( ++ {inv_cell_, ++ prefix, ++ "out_inv", ++ {{inv_ports_[{PortRoleType::DataIn, 0}], root.net}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], out}}}); ++ } ++ } ++ } ++ } ++ } ++ + for (int row = 0; row < num_rows; ++row) { + // one select_b_net per row for column_mux_ratio > 1 + vector shared_select_b_nets(r_total); +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index c4584484fa..fed815886b 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -42,7 +42,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* tristate_cell_name, + const char* inv_cell_name, + const char* tapcell_name, +- const int max_tap_dist) ++ const int max_tap_dist, ++ const char* read_style) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -94,7 +95,7 @@ generate_ram_netlist_cmd(int mask_size, + + ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, +- tapcell, max_tap_dist); ++ tapcell, max_tap_dist, read_style); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 6ca3a68023..2eb5896319 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -7,6 +7,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-column_mux_ratio ratio] + [-storage_cell name] + [-tristate_cell name] ++ [-read_style tristate|and_or] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -19,7 +20,7 @@ proc generate_ram_netlist { args } { + sta::parse_key_args "generate_ram_netlist" args \ + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist +- -write_behavioral_verilog } flags {} ++ -write_behavioral_verilog -read_style } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -133,8 +134,19 @@ proc generate_ram_netlist { args } { + ram::set_behavioral_verilog_filename $keys(-write_behavioral_verilog) + } + ++ # The read path: tristate bitlines, or AND-OR trees (and_or). By default ++ # tristate where the library has a tristate cell, and_or where not. ++ set read_style "" ++ if { [info exists keys(-read_style)] } { ++ set read_style $keys(-read_style) ++ if { $read_style ni {tristate and_or} } { ++ utl::error RAM 56 "-read_style is tristate or and_or, not $read_style." ++ } ++ } ++ + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ +- $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist ++ $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ ++ $read_style + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -146,6 +158,7 @@ sta::define_cmd_args "generate_ram" {[-mask_size bits] + [-column_mux_ratio ratio] + [-storage_cell name] + [-tristate_cell name] ++ [-read_style tristate|and_or] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -167,7 +180,7 @@ proc generate_ram { args } { + -r_ports -w_ports -use_latch -power_net_name + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist +- -write_behavioral_verilog } flags {} ++ -write_behavioral_verilog -read_style } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -204,6 +217,10 @@ proc generate_ram { args } { + lappend ram_netlist_args -tristate_cell $keys(-tristate_cell) + } + ++ if { [info exists keys(-read_style)] } { ++ lappend ram_netlist_args -read_style $keys(-read_style) ++ } ++ + if { [info exists keys(-inv_cell)] } { + lappend ram_netlist_args -inv_cell $keys(-inv_cell) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index cec5372c33..87d3ef72a7 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_2r1w_and_or_asap7", + "make_7x7_1r2w_nangate45", + "generate_regfile_asap7", + "generate_regfile_clock_gate_asap7", +@@ -91,6 +92,11 @@ filegroup( + "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ + "generate_regfile_asap7.regfile", + ], ++ "make_8x8_2r1w_and_or_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_and_or_asap7_behavioral.vok", ++ ], + "make_7x7_1r2w_nangate45": [ + "make_7x7_1r2w_nangate45_behavioral.vok", + "Nangate45/Nangate45.lef", +diff --git a/src/ram/test/make_8x8_2r1w_and_or_asap7.defok b/src/ram/test/make_8x8_2r1w_and_or_asap7.defok +new file mode 100644 +index 0000000000..736da756aa +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_and_or_asap7.defok +@@ -0,0 +1,672 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 1803 243 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 334 BY 1 STEP 5 0 ; ++COMPONENTS 281 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 216 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 172 216 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 345 216 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 518 216 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 691 216 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 864 216 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1036 216 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 1209 216 ) N ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1533 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1533 27 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1533 54 ) N ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1533 81 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1533 108 ) N ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1533 135 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1533 162 ) N ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1533 189 ) FS ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1566 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1566 27 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1566 54 ) N ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1566 81 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1566 108 ) N ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1566 135 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1566 162 ) N ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1566 189 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 1771 108 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 1771 54 ) N ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 1771 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1620 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1620 27 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1620 54 ) N ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1620 81 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1620 108 ) N ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1620 135 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1620 162 ) N ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1620 189 ) FS ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1652 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1652 27 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1652 54 ) N ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1652 81 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1652 108 ) N ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1652 135 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1652 162 ) N ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1652 189 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 1771 135 ) FS ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 1771 81 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 1771 27 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1706 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1706 27 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1706 54 ) N ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1706 81 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1706 108 ) N ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1706 135 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1706 162 ) N ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1706 189 ) FS ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1738 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1738 27 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1738 54 ) N ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1738 81 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1738 108 ) N ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1738 135 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1738 162 ) N ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1738 189 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 1787 108 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 1787 54 ) N ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 1787 0 ) N ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 108 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 108 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 108 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 280 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 280 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 280 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 280 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 453 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 453 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 453 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 626 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 626 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 626 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 626 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 799 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 799 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 799 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 799 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 972 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 972 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 972 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 972 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 972 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1317 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 140 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 140 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 129 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 129 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 129 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 313 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 313 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 313 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 302 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 302 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 302 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 486 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 486 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 475 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 658 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 658 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 658 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 648 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 648 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 831 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 831 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 831 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 820 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 993 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 993 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 993 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1166 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1339 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1598 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1598 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1598 54 ) N ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1598 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1598 108 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1598 135 ) FS ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1598 162 ) N ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1598 189 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1684 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1684 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1684 54 ) N ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1684 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1684 108 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1684 135 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1684 162 ) N ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1684 189 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1512 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1512 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1512 54 ) N ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1512 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1512 108 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1512 135 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1512 162 ) N ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1512 189 ) FS ; ++ - storage_0_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - storage_0_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - storage_0_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - storage_0_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - storage_0_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - storage_0_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - storage_0_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - storage_0_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - storage_0_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 0 ) N ; ++ - storage_0_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 81 ) FS ; ++ - storage_4_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 108 ) N ; ++ - storage_4_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 108 ) N ; ++ - storage_4_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 108 ) N ; ++ - storage_5_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 135 ) FS ; ++ - storage_5_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 135 ) FS ; ++ - storage_5_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 135 ) FS ; ++ - storage_6_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 162 ) N ; ++ - storage_6_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 162 ) N ; ++ - storage_6_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 162 ) N ; ++ - storage_7_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 189 ) FS ; ++ - storage_7_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 189 ) FS ; ++ - storage_7_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 189 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 300 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_7_0_0.bit0.bit D ) ( storage_6_0_0.bit0.bit D ) ( storage_5_0_0.bit0.bit D ) ( storage_4_0_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ++ ( storage_1_0_0.bit0.bit D ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_7_0_0.bit1.bit D ) ( storage_6_0_0.bit1.bit D ) ( storage_5_0_0.bit1.bit D ) ( storage_4_0_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ++ ( storage_1_0_0.bit1.bit D ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_7_0_0.bit2.bit D ) ( storage_6_0_0.bit2.bit D ) ( storage_5_0_0.bit2.bit D ) ( storage_4_0_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ++ ( storage_1_0_0.bit2.bit D ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_7_0_0.bit3.bit D ) ( storage_6_0_0.bit3.bit D ) ( storage_5_0_0.bit3.bit D ) ( storage_4_0_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ++ ( storage_1_0_0.bit3.bit D ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_7_0_0.bit4.bit D ) ( storage_6_0_0.bit4.bit D ) ( storage_5_0_0.bit4.bit D ) ( storage_4_0_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ++ ( storage_1_0_0.bit4.bit D ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_7_0_0.bit5.bit D ) ( storage_6_0_0.bit5.bit D ) ( storage_5_0_0.bit5.bit D ) ( storage_4_0_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ++ ( storage_1_0_0.bit5.bit D ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_7_0_0.bit6.bit D ) ( storage_6_0_0.bit6.bit D ) ( storage_5_0_0.bit6.bit D ) ( storage_4_0_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ++ ( storage_1_0_0.bit6.bit D ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_7_0_0.bit7.bit D ) ( storage_6_0_0.bit7.bit D ) ( storage_5_0_0.bit7.bit D ) ( storage_4_0_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ++ ( storage_1_0_0.bit7.bit D ) ( storage_0_0_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.cg CLK ) ( storage_6_0_0.cg CLK ) ( storage_5_0_0.cg CLK ) ( storage_4_0_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_0_0.cg CLK ) ++ ( storage_1_0_0.cg CLK ) ( storage_0_0_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A1 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A1 ) ++ ( read_w0_p0_b1.aoi_r0 A1 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A1 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A1 ) ++ ( read_w0_p1_b1.aoi_r0 A1 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.storage ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A2 ) ( storage_0_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.storage ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( storage_0_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.storage ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( storage_0_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.storage ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( storage_0_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.storage ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A2 ) ( storage_0_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.storage ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( storage_0_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.storage ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( storage_0_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.storage ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A2 ) ( storage_0_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.gclock ( storage_0_0_0.cg GCLK ) ( storage_0_0_0.bit7.bit CLK ) ( storage_0_0_0.bit6.bit CLK ) ( storage_0_0_0.bit5.bit CLK ) ( storage_0_0_0.bit4.bit CLK ) ( storage_0_0_0.bit3.bit CLK ) ( storage_0_0_0.bit2.bit CLK ) ++ ( storage_0_0_0.bit1.bit CLK ) ( storage_0_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_0_0.we ( storage_0_0_0.gcand Y ) ( storage_0_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.gclock ( storage_4_0_0.cg GCLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.gcand Y ) ( storage_4_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.gclock ( storage_5_0_0.cg GCLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.gcand Y ) ( storage_5_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.gclock ( storage_6_0_0.cg GCLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.gcand Y ) ( storage_6_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.gclock ( storage_7_0_0.cg GCLK ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.gcand Y ) ( storage_7_0_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) ( storage_0_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_7_0_0.gcand B ) ( storage_6_0_0.gcand B ) ( storage_5_0_0.gcand B ) ( storage_4_0_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_0_0.gcand B ) ++ ( storage_1_0_0.gcand B ) ( storage_0_0_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_and_or_asap7.tcl b/src/ram/test/make_8x8_2r1w_and_or_asap7.tcl +new file mode 100644 +index 0000000000..8b38e0a7f4 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_and_or_asap7.tcl +@@ -0,0 +1,31 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees, and the storage flop's only output is QN. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_and_or_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_and_or_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_and_or_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_and_or_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_and_or_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_and_or_asap7_behavioral.vok +new file mode 100644 +index 0000000000..a5a0666525 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_and_or_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i]) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index d6ce26bfc6..cb958fabc3 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -6,5 +6,6 @@ record_tests { + make_8x8_2r1w_sky130 + make_7x7_2r1w_nangate45 + make_7x7_1r2w_nangate45 ++ make_8x8_2r1w_and_or_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 7ee28d607..c4911e862 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -174,6 +174,7 @@ test_suite( "@openroad//src/ram/test:make_7x7_1r2w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_2r1w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_and_or_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_sky130-tcl_test", ], diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 66a4058c5..bb12ed9cd 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -121,65 +121,103 @@ stdcell_verilog( libs = ["@orfs//flow:platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib"], ) -genrule( - name = "ram_2w_v", - srcs = [ +NANGATE45 = { + "lefs": [ "@orfs//flow:platforms/nangate45/lef/NangateOpenCellLibrary.tech.lef", "@orfs//flow:platforms/nangate45/lef/NangateOpenCellLibrary.macro.mod.lef", - "@orfs//flow:platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib", ], - outs = [ - "ram_2w_gen.v", - "ram_2w_model.v", - ], - cmd = """ -cat > $(@D)/ram_2w.tcl < $(@D)/ram_2w.log 2>&1 || { cat $(@D)/ram_2w.log; exit 1; } -# write_verilog needs the network linked to the block, as reading it back -# does -cat > $(@D)/ram_2w_v.tcl <> $(@D)/ram_2w.log 2>&1 || { cat $(@D)/ram_2w.log; exit 1; } -sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/ram_2w.v > $(location ram_2w_gen.v) -""", - tools = ["@openroad"], -) - -verilog_library( - name = "tb_ram_2w_rtl", - srcs = [ - "tb_ram_2w.v", + "libs": ["@orfs//flow:platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib"], + "stdcell": [ ":nangate45_stdcell.v", ":nangate45_stdcell_empty.v", - ":ram_2w_gen.v", - ":ram_2w_model.v", ], -) +} -verilator_cc_library( - name = "tb_ram_2w", - module = ":tb_ram_2w_rtl", - module_top = "tb_ram_2w", - trace_mode = "none", - vopts = [ - "-Wno-fatal", - "--x-initial", - "0", +ASAP7 = { + "lefs": [ + "@orfs//flow:platforms/asap7/lef/asap7_tech_1x_201209.lef", + "@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef", ], -) + "libs": [ + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_AO_RVT_TT_nldm_211120.lib.gz", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_INVBUF_RVT_TT_nldm_220122.lib.gz", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_OA_RVT_TT_nldm_211120.lib.gz", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_SEQ_RVT_TT_nldm_220123.lib", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_SIMPLE_RVT_TT_nldm_211120.lib.gz", + ], + "stdcell": [ + ":asap7_stdcell.v", + ":asap7_stdcell_empty.v", + ], +} -cc_test( - name = "ram_2w_sim_test", - size = "small", - srcs = ["tb_ram_2w.cc"], - deps = [":tb_ram_2w"], -) +# Each shape of generate_ram's 8 x 8, two write ports and one read: +# Nangate45's tristate bitlines (patch 0011), its AND-OR trees asked for +# (patch 0012), and asap7's, which has no tristate cell, with its QN-only +# flop (the storage cell named: the smallest flop is negative-edge). +[ + [ + genrule( + name = "%s_v" % name, + srcs = platform["lefs"] + platform["libs"], + outs = [ + "%s_gen.v" % name, + "%s_model.v" % name, + ], + cmd = """ +cat > $(@D)/{name}.tcl < $(@D)/{name}.log 2>&1 || {{ cat $(@D)/{name}.log; exit 1; }} +# write_verilog needs the network linked to the block, as reading it back +# does +cat > $(@D)/{name}_v.tcl <> $(@D)/{name}.log 2>&1 || {{ cat $(@D)/{name}.log; exit 1; }} +sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_gen.v) +""".format( + name = name, + args = args, + read_lefs = "\n".join(["read_lef $(location %s)" % f for f in platform["lefs"]]), + read_libs = "\n".join(["read_liberty $(location %s)" % f for f in platform["libs"]]), + ), + tools = ["@openroad"], + ), + verilog_library( + name = "tb_%s_rtl" % name, + srcs = [ + "tb_ram_2w.v", + ":%s_gen.v" % name, + ":%s_model.v" % name, + ] + platform["stdcell"], + ), + verilator_cc_library( + name = "tb_%s" % name, + module = ":tb_%s_rtl" % name, + module_top = "tb_ram_2w", + trace_mode = "none", + vopts = [ + "-Wno-fatal", + "--x-initial", + "0", + ], + ), + cc_test( + name = "%s_sim_test" % name, + size = "small", + srcs = ["tb_ram_2w.cc"], + deps = [":tb_%s" % name], + ), + ] + for name, platform, args in [ + ("ram_2w", NANGATE45, "-storage_cell DFF_X1"), + ("ram_2w_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or"), + ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R"), + ] +] From 5a8be7986f01875102a1ba8f54967af574c8fd5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 08:29:02 +0200 Subject: [PATCH 12/26] ram: generate_ram -zero_word, a word that reads 0 (patch 0013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The third generate_regfile feature carried onto generate_ram, on 0012: -zero_word n reads 0 at word n and drops its writes, as a RISC-V x0. The row keeps its place in the grid without flops or clock gate, and the AND-OR trees are built over the other rows; with an inverted storage output the zero word stays in them with its own select as its term, so the root's inverter reads it as 0. Needs the AND-OR read path. Tests: make_8x8_2r1w_zero_asap7 in generate_ram's format; and the two-write RAM simulated with a zero word on asap7 (QN flops) and on Nangate45's trees (Q flops), 20 008 cycles each, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + patches/0013-openroad-ram-zero-word.patch | 1176 +++++++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 5 +- 4 files changed, 1184 insertions(+), 1 deletion(-) create mode 100644 patches/0013-openroad-ram-zero-word.patch diff --git a/MODULE.bazel b/MODULE.bazel index 99dd2d08f..26537706e 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -136,6 +136,9 @@ archive_override( # has no tristate cell (asap7), or when asked; a QN-only storage # flop taken there. On 0011 (OpenROAD #11669); not upstreamed. "//patches:0012-openroad-ram-and-or-read.patch", + # 0013: generate_ram -zero_word, a word that reads 0 and drops its + # writes (a RISC-V x0). On 0012 (OpenROAD #11669); not upstreamed. + "//patches:0013-openroad-ram-zero-word.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0013-openroad-ram-zero-word.patch b/patches/0013-openroad-ram-zero-word.patch new file mode 100644 index 000000000..1a7d23b57 --- /dev/null +++ b/patches/0013-openroad-ram-zero-word.patch @@ -0,0 +1,1176 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -zero_word, a word that reads 0 + +-zero_word n makes word n read 0 and drop its writes, as a RISC-V +register file's x0: its row keeps its place in the grid but has no +flops and no clock gate, and the AND-OR read trees are built over the +other rows; where the storage flop's output is inverted the zero word +stays in them, its term its own select, so the inverter at the root +reads it as 0. The behavioral model reads 0 there and ignores writes. +Needs -read_style and_or and -column_mux_ratio 1 (RAM-0060). + +The third of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index f7981d19fc..c73f269d6c 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -44,6 +44,7 @@ generate_ram [-mask_size bits] + [-storage_cell name] + [-tristate_cell name] + [-read_style tristate|and_or] ++ [-zero_word word] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -70,6 +71,7 @@ generate_ram [-mask_size bits] + | `-storage_cell` | Name of the master to use for the storage device (i.e. a flip-flop). Must be positive-edge triggered. Default: auto-select from the loaded cell library. | + | `-tristate_cell` | Name of the master to use for the tristate device (i.e. a tristate inverter). It is currently assumed that the device is inverting. Default: auto-select from the loaded cell library. | + | `-read_style` | The read path: `tristate`, a tristate bitline per bit, or `and_or`, a tree per bit column of an AOI22 over each pair of rows and NAND2 and NOR2 levels above, for a library without a tristate cell. `and_or` also takes a storage flop whose only output is inverted (QN). Default: `tristate` where the library has a tristate cell, `and_or` where it has none. | ++| `-zero_word` | A word that reads 0 and drops its writes, as a RISC-V register file's x0: its row has no flops or clock gate, and the read trees leave it out. Needs `-read_style and_or` and `-column_mux_ratio 1`. Default: none. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index db535732f0..e7fc10c122 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -110,7 +110,8 @@ class RamGen + odb::dbMaster* inv_cell, + odb::dbMaster* tapcell, + int max_tap_dist, +- const std::string& read_style = ""); ++ const std::string& read_style = "", ++ int zero_word = -1); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -156,9 +157,11 @@ class RamGen + odb::dbNet* net; + bool inverted; // the net is the complement of the OR of the terms + }; ++ // the tree over rows[lo, hi): rows lists the rows that store a word + TreeEnd planReadTree(const std::string& prefix, + int word_idx, + int bit, ++ const std::vector& rows, + int lo, + int hi, + const std::vector& selects, +@@ -311,6 +314,7 @@ class RamGen + bool and_or_read_{false}; + std::string read_style_; + bool storage_inverted_{false}; // the storage flop's output is QN ++ int zero_word_{-1}; // the word that reads 0 and is not stored, or -1 + // per (row, word in the row, bit): the storage net, and the tree + // cells placed in that bit's cell + std::map, odb::dbNet*> storage_nets_; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 463e1f3a86..7362a35c8e 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -181,6 +181,7 @@ bool RamGen::treeInverted(const int lo, const int hi) const + RamGen::TreeEnd RamGen::planReadTree(const std::string& prefix, + const int word_idx, + const int bit, ++ const vector& rows, + const int lo, + const int hi, + const vector& selects, +@@ -192,32 +193,39 @@ RamGen::TreeEnd RamGen::planReadTree(const std::string& prefix, + const vector>& conns) { + tree_nodes_[{row, word_idx, bit}].push_back({master, prefix, name, conns}); + }; ++ // the zero word's term, where the trees read inverted data: its own ++ // select, the inverted form of a stored 0 (the zero word is in the ++ // tree only then) + auto q = [&](const int row) { +- return storage_nets_.at({row, word_idx, bit}); ++ return row == zero_word_ ? selects[row] ++ : storage_nets_.at({row, word_idx, bit}); + }; + auto net = [&](dbNet* given) { + return given ? given : makeNet(prefix, fmt::format("t{}_{}", lo, hi)); + }; + const int n = hi - lo; + if (n == 1) { ++ const int r = rows[lo]; + dbNet* y = net(out); +- add(lo, ++ add(r, + nand2_cell_, +- fmt::format("nand_r{}", lo), +- {{nand2_ports_[{PortRoleType::DataIn, 0}], selects[lo]}, +- {nand2_ports_[{PortRoleType::DataIn, 1}], q(lo)}, ++ fmt::format("nand_r{}", r), ++ {{nand2_ports_[{PortRoleType::DataIn, 0}], selects[r]}, ++ {nand2_ports_[{PortRoleType::DataIn, 1}], q(r)}, + {nand2_ports_[{PortRoleType::DataOut, 0}], y}}); + return {y, true}; + } + if (n == 2) { ++ const int r0 = rows[lo]; ++ const int r1 = rows[lo + 1]; + dbNet* y = net(out); +- add(lo, ++ add(r0, + aoi22_cell_, +- fmt::format("aoi_r{}", lo), +- {{aoi22_in_a1_, selects[lo]}, +- {aoi22_in_a2_, q(lo)}, +- {aoi22_in_b1_, selects[lo + 1]}, +- {aoi22_in_b2_, q(lo + 1)}, ++ fmt::format("aoi_r{}", r0), ++ {{aoi22_in_a1_, selects[r0]}, ++ {aoi22_in_a2_, q(r0)}, ++ {aoi22_in_b1_, selects[r1]}, ++ {aoi22_in_b2_, q(r1)}, + {aoi22_out_, y}}); + return {y, true}; + } +@@ -226,13 +234,14 @@ RamGen::TreeEnd RamGen::planReadTree(const std::string& prefix, + half *= 2; + } + const int mid = lo + half; +- const int host = mid - 1; ++ const int host = rows[mid - 1]; + const TreeEnd a +- = planReadTree(prefix, word_idx, bit, lo, mid, selects, nullptr); +- TreeEnd b = planReadTree(prefix, word_idx, bit, mid, hi, selects, nullptr); ++ = planReadTree(prefix, word_idx, bit, rows, lo, mid, selects, nullptr); ++ TreeEnd b ++ = planReadTree(prefix, word_idx, bit, rows, mid, hi, selects, nullptr); + if (b.inverted != a.inverted) { + dbNet* nb = makeNet(prefix, fmt::format("t{}_{}_inv", mid, hi)); +- add(mid, ++ add(rows[mid], + inv_cell_, + fmt::format("inv_r{}_{}", mid, hi), + {{inv_ports_[{PortRoleType::DataIn, 0}], b.net}, +@@ -288,6 +297,29 @@ void RamGen::makeSlice(const int slice_idx, + std::string prefix + = fmt::format("storage_{}_{}_{}", row_idx, word_idx, start_bit_idx); + ++ // The zero word: no flops, no clock gate; its row's cells hold only ++ // the read trees' nodes planned there. ++ if (row_idx == zero_word_) { ++ for (int local_bit = 0; local_bit < mask_size; ++local_bit) { ++ const int bit = start_bit_idx + local_bit; ++ std::unique_ptr cell; ++ auto nodes = tree_nodes_.find({row_idx, word_idx, bit}); ++ if (nodes != tree_nodes_.end() && !nodes->second.empty()) { ++ cell = std::make_unique(); ++ for (const auto& node : nodes->second) { ++ makeInst(cell.get(), node.prefix, node.name, node.master, node.conns); ++ } ++ } ++ ram_grid_.addCell(std::move(cell), ++ slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) ++ + local_bit * column_mux_ratio + word_idx); ++ } ++ ram_grid_.addCell(nullptr, ++ slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) ++ + mask_size * column_mux_ratio + word_idx); ++ return; ++ } ++ + int r_total = rw_ports + r_ports; + vector select_b_nets(r_total); + if (and_or_read_) { +@@ -1525,7 +1557,8 @@ void RamGen::generate(const int mask_size, + dbMaster* inv_cell, + dbMaster* tapcell, + int max_tap_dist, +- const std::string& read_style) ++ const std::string& read_style, ++ const int zero_word) + { + if (num_words / column_mux_ratio == 1) { + logger_->error(RAM, 42, "1-row RAMs are not supported."); +@@ -1573,6 +1606,7 @@ void RamGen::generate(const int mask_size, + use_latch_ = use_latch; + num_write_ = rw_ports + w_ports; + read_style_ = read_style; ++ zero_word_ = zero_word; + and_or_read_ = false; + storage_inverted_ = false; + storage_nets_.clear(); +@@ -1617,6 +1651,24 @@ void RamGen::generate(const int mask_size, + + findMasters(); + ++ // A zero word reads 0 and drops its writes, as a RISC-V x0: its row ++ // has no flops, and the read trees leave it out. ++ if (zero_word_ >= 0) { ++ if (zero_word_ >= num_words) { ++ logger_->error(RAM, ++ 59, ++ "-zero_word {} is not a word of {}.", ++ zero_word_, ++ num_words); ++ } ++ if (!and_or_read_ || column_mux_ratio != 1) { ++ logger_->error(RAM, ++ 60, ++ "-zero_word needs -read_style and_or and " ++ "-column_mux_ratio 1."); ++ } ++ } ++ + auto chip = db_->getChip(); + if (!chip) { + chip = odb::dbChip::create( +@@ -1839,7 +1891,19 @@ void RamGen::generate(const int mask_size, + // Where the storage flop's output is QN, or the tree's root is + // inverted, but not both, an inverter at the bottom row puts it right. + if (and_or_read_) { ++ // The rows in the trees: where the storage output is inverted the ++ // final inverter assumes some row's term is the read's, so the zero ++ // word stays, its term a 1; otherwise its term would be a 0, and it ++ // is left out. ++ vector stored_rows; + for (int row = 0; row < num_rows; ++row) { ++ if (row == zero_word_) { ++ if (storage_inverted_) { ++ stored_rows.push_back(row); ++ } ++ continue; ++ } ++ stored_rows.push_back(row); + for (int w = 0; w < column_mux_ratio; ++w) { + for (int bit = 0; bit < word_size; ++bit) { + const std::string prefix = fmt::format( +@@ -1849,7 +1913,8 @@ void RamGen::generate(const int mask_size, + } + } + } +- const bool flip = treeInverted(0, num_rows) != storage_inverted_; ++ const int stored = static_cast(stored_rows.size()); ++ const bool flip = treeInverted(0, stored) != storage_inverted_; + for (int w = 0; w < column_mux_ratio; ++w) { + for (int port = 0; port < r_total; ++port) { + for (int bit = 0; bit < word_size; ++bit) { +@@ -1860,8 +1925,9 @@ void RamGen::generate(const int mask_size, + = planReadTree(prefix, + w, + bit, ++ stored_rows, + 0, +- num_rows, ++ stored, + read_select_nets[port], + flip ? nullptr : out); + if (flip) { +@@ -2451,12 +2517,24 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + if (i > 0) { + read_port_logic += "\n"; + } +- read_port_logic += fmt::format(R"( always @(*) begin ++ if (zero_word_ >= 0) { ++ read_port_logic += fmt::format(R"( always @(*) begin ++ {} = {} == {} ? {}'d0 : mem[{}]; ++ end ++)", ++ port_name, ++ addr_name, ++ zero_word_, ++ word_size_bit, ++ addr_name); ++ } else { ++ read_port_logic += fmt::format(R"( always @(*) begin + {} = mem[{}]; + end + )", +- port_name, +- addr_name); ++ port_name, ++ addr_name); ++ } + } + + // Write logic, the ports in order: where two write the same word in a +@@ -2472,13 +2550,18 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + enable_declarations += fmt::format( + " input [{}:0] {};\n", slices_per_word - 1, wbus("we", w)); + write_logic += fmt::format(R"( for (i = 0; i < {}; i = i + 1) begin +- if ({}[i]) begin ++ if ({}[i]{}) begin + mem[{}][i*{} +:{}] <= {}[i*{} +:{}]; + end + end + )", + slices_per_word, + wbus("we", w), ++ zero_word_ >= 0 ++ ? fmt::format(" && {} != {}", ++ write_addr, ++ zero_word_) ++ : std::string(), + write_addr, + mask_size, + mask_size, +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index fed815886b..5f765b215b 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -43,7 +43,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* inv_cell_name, + const char* tapcell_name, + const int max_tap_dist, +- const char* read_style) ++ const char* read_style, ++ const int zero_word) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -95,7 +96,7 @@ generate_ram_netlist_cmd(int mask_size, + + ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, +- tapcell, max_tap_dist, read_style); ++ tapcell, max_tap_dist, read_style, zero_word); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 2eb5896319..998f61fde5 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -8,6 +8,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-storage_cell name] + [-tristate_cell name] + [-read_style tristate|and_or] ++ [-zero_word word] ++ [-zero_word word] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -20,7 +22,7 @@ proc generate_ram_netlist { args } { + sta::parse_key_args "generate_ram_netlist" args \ + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist +- -write_behavioral_verilog -read_style } flags {} ++ -write_behavioral_verilog -read_style -zero_word } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -144,9 +146,15 @@ proc generate_ram_netlist { args } { + } + } + ++ # A word that reads 0 and drops its writes, as a RISC-V x0. ++ set zero_word -1 ++ if { [info exists keys(-zero_word)] } { ++ set zero_word $keys(-zero_word) ++ } ++ + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ +- $read_style ++ $read_style $zero_word + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -180,7 +188,7 @@ proc generate_ram { args } { + -r_ports -w_ports -use_latch -power_net_name + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist +- -write_behavioral_verilog -read_style } flags {} ++ -write_behavioral_verilog -read_style -zero_word } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -221,6 +229,10 @@ proc generate_ram { args } { + lappend ram_netlist_args -read_style $keys(-read_style) + } + ++ if { [info exists keys(-zero_word)] } { ++ lappend ram_netlist_args -zero_word $keys(-zero_word) ++ } ++ + if { [info exists keys(-inv_cell)] } { + lappend ram_netlist_args -inv_cell $keys(-inv_cell) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 87d3ef72a7..0bd0331ed9 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_2r1w_zero_asap7", + "make_8x8_2r1w_and_or_asap7", + "make_7x7_1r2w_nangate45", + "generate_regfile_asap7", +@@ -92,6 +93,11 @@ filegroup( + "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ + "generate_regfile_asap7.regfile", + ], ++ "make_8x8_2r1w_zero_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_zero_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_zero_asap7.defok b/src/ram/test/make_8x8_2r1w_zero_asap7.defok +new file mode 100644 +index 0000000000..33234d5b80 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_zero_asap7.defok +@@ -0,0 +1,653 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 1803 243 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 334 BY 1 STEP 5 0 ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 334 BY 1 STEP 5 0 ; ++COMPONENTS 271 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 216 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 172 216 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 345 216 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 518 216 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 691 216 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 864 216 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1036 216 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 1209 216 ) N ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1533 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1533 27 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1533 54 ) N ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1533 81 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1533 108 ) N ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1533 135 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1533 162 ) N ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1533 189 ) FS ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1566 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1566 27 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1566 54 ) N ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1566 81 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1566 108 ) N ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1566 135 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1566 162 ) N ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1566 189 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 1771 108 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 1771 54 ) N ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 1771 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1620 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1620 27 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1620 54 ) N ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1620 81 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1620 108 ) N ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1620 135 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1620 162 ) N ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1620 189 ) FS ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1652 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1652 27 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1652 54 ) N ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1652 81 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1652 108 ) N ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1652 135 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1652 162 ) N ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1652 189 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 1771 135 ) FS ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 1771 81 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 1771 27 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1706 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1706 27 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1706 54 ) N ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1706 81 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1706 108 ) N ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1706 135 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1706 162 ) N ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1706 189 ) FS ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1738 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1738 27 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1738 54 ) N ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1738 81 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1738 108 ) N ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1738 135 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1738 162 ) N ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1738 189 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 1787 108 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 1787 54 ) N ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 1787 0 ) N ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 108 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 108 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 108 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 280 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 280 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 280 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 453 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 453 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 453 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 626 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 626 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 626 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 799 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 799 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 799 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 972 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 972 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 972 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 972 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1317 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 32 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 140 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 140 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 129 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 129 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 129 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 205 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 313 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 313 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 302 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 302 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 302 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 378 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 486 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 486 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 475 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 550 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 658 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 658 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 648 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 648 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 723 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 831 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 831 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 820 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 896 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 993 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 993 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 993 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1069 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1166 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1242 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1339 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1598 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1598 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1598 54 ) N ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1598 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1598 108 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1598 135 ) FS ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1598 162 ) N ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1598 189 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1684 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1684 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1684 54 ) N ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1684 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1684 108 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1684 135 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1684 162 ) N ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1684 189 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1512 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1512 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1512 54 ) N ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1512 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1512 108 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1512 135 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1512 162 ) N ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1512 189 ) FS ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 81 ) FS ; ++ - storage_4_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 108 ) N ; ++ - storage_4_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 108 ) N ; ++ - storage_4_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 108 ) N ; ++ - storage_5_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 135 ) FS ; ++ - storage_5_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 135 ) FS ; ++ - storage_5_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 135 ) FS ; ++ - storage_6_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 162 ) N ; ++ - storage_6_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 162 ) N ; ++ - storage_6_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 162 ) N ; ++ - storage_7_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 189 ) FS ; ++ - storage_7_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 189 ) FS ; ++ - storage_7_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 189 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 290 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_7_0_0.bit0.bit D ) ( storage_6_0_0.bit0.bit D ) ( storage_5_0_0.bit0.bit D ) ( storage_4_0_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ++ ( storage_1_0_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_7_0_0.bit1.bit D ) ( storage_6_0_0.bit1.bit D ) ( storage_5_0_0.bit1.bit D ) ( storage_4_0_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ++ ( storage_1_0_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_7_0_0.bit2.bit D ) ( storage_6_0_0.bit2.bit D ) ( storage_5_0_0.bit2.bit D ) ( storage_4_0_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ++ ( storage_1_0_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_7_0_0.bit3.bit D ) ( storage_6_0_0.bit3.bit D ) ( storage_5_0_0.bit3.bit D ) ( storage_4_0_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ++ ( storage_1_0_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_7_0_0.bit4.bit D ) ( storage_6_0_0.bit4.bit D ) ( storage_5_0_0.bit4.bit D ) ( storage_4_0_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ++ ( storage_1_0_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_7_0_0.bit5.bit D ) ( storage_6_0_0.bit5.bit D ) ( storage_5_0_0.bit5.bit D ) ( storage_4_0_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ++ ( storage_1_0_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_7_0_0.bit6.bit D ) ( storage_6_0_0.bit6.bit D ) ( storage_5_0_0.bit6.bit D ) ( storage_4_0_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ++ ( storage_1_0_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_7_0_0.bit7.bit D ) ( storage_6_0_0.bit7.bit D ) ( storage_5_0_0.bit7.bit D ) ( storage_4_0_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ++ ( storage_1_0_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.cg CLK ) ( storage_6_0_0.cg CLK ) ( storage_5_0_0.cg CLK ) ( storage_4_0_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_0_0.cg CLK ) ++ ( storage_1_0_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A1 ) ++ ( read_w0_p0_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A1 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A1 ) ++ ( read_w0_p0_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p1_b5.aoi_r0 A1 ) ++ ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p1_b2.aoi_r0 A1 ) ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p1_b1.aoi_r0 A1 ) ++ ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.gclock ( storage_4_0_0.cg GCLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.gcand Y ) ( storage_4_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.gclock ( storage_5_0_0.cg GCLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.gcand Y ) ( storage_5_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.gclock ( storage_6_0_0.cg GCLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.gcand Y ) ( storage_6_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.gclock ( storage_7_0_0.cg GCLK ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.gcand Y ) ( storage_7_0_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_7_0_0.gcand B ) ( storage_6_0_0.gcand B ) ( storage_5_0_0.gcand B ) ( storage_4_0_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_0_0.gcand B ) ++ ( storage_1_0_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_zero_asap7.tcl b/src/ram/test/make_8x8_2r1w_zero_asap7.tcl +new file mode 100644 +index 0000000000..83d65a7d08 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_zero_asap7.tcl +@@ -0,0 +1,33 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees, the storage flop's only output is QN, and word 0 reads ++# 0 (a RISC-V x0). ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_zero_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -zero_word 0 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_zero_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_zero_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_zero_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_zero_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_zero_asap7_behavioral.vok +new file mode 100644 +index 0000000000..373f465efb +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_zero_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i] && addr_w != 0) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = addr_r0 == 0 ? 8'd0 : mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = addr_r1 == 0 ? 8'd0 : mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index cb958fabc3..ad53c742b5 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -7,5 +7,6 @@ record_tests { + make_7x7_2r1w_nangate45 + make_7x7_1r2w_nangate45 + make_8x8_2r1w_and_or_asap7 ++ make_8x8_2r1w_zero_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index c4911e862..4dbbc25c9 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -176,6 +176,7 @@ test_suite( "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_and_or_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_sky130-tcl_test", ], ) diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index bb12ed9cd..aade170a6 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -154,7 +154,8 @@ ASAP7 = { # Each shape of generate_ram's 8 x 8, two write ports and one read: # Nangate45's tristate bitlines (patch 0011), its AND-OR trees asked for # (patch 0012), and asap7's, which has no tristate cell, with its QN-only -# flop (the storage cell named: the smallest flop is negative-edge). +# flop (the storage cell named: the smallest flop is negative-edge), and +# with a word reading 0 (patch 0013), on either polarity of flop. [ [ genrule( @@ -218,6 +219,8 @@ sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_g for name, platform, args in [ ("ram_2w", NANGATE45, "-storage_cell DFF_X1"), ("ram_2w_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or"), + ("ram_2w_and_or_zero", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -zero_word 3"), ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R"), + ("ram_2w_asap7_zero", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -zero_word 0"), ] ] From e2602a1145717d3c8b357cfbcacec80370ab67ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 08:46:30 +0200 Subject: [PATCH 13/26] ram: generate_ram -reset_value, an asynchronous reset (patch 0014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fourth generate_regfile feature carried onto generate_ram, on 0013: -reset_value v resets every word to v asynchronously. Each bit's flop is cleared or preset, the other pin held off by a tie per word slice; the pins come from the flop's ff group, and which gives which value counts the flop's output polarity (asap7's DFFASRHQNx1 stores !D). The reset port takes the flop's polarity, rst_n or rst; a parent adapts any other. An option, off by default: ibex, cva6, ariane, swerv and coralnpu reset their register files, each for reasons of its own. Tests: make_8x8_2r1w_reset_asap7 in generate_ram's format; the two-write RAM with -reset_value 0xa5 simulated on Nangate45 (tristates and trees, DFFRS_X1) and asap7: every word checked after each reset, random resets among 20 000 cycles of writes on both ports, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 4 + patches/0014-openroad-ram-reset.patch | 1342 +++++++++++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 25 +- test/regfile/sim/tb_ram_2w_rst.cc | 64 ++ test/regfile/sim/tb_ram_2w_rst.v | 25 + 6 files changed, 1451 insertions(+), 10 deletions(-) create mode 100644 patches/0014-openroad-ram-reset.patch create mode 100644 test/regfile/sim/tb_ram_2w_rst.cc create mode 100644 test/regfile/sim/tb_ram_2w_rst.v diff --git a/MODULE.bazel b/MODULE.bazel index 26537706e..ef5a7448f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -139,6 +139,10 @@ archive_override( # 0013: generate_ram -zero_word, a word that reads 0 and drops its # writes (a RISC-V x0). On 0012 (OpenROAD #11669); not upstreamed. "//patches:0013-openroad-ram-zero-word.patch", + # 0014: generate_ram -reset_value, an asynchronous reset of every + # word, per bit cleared or preset. On 0013 (OpenROAD #11669); not + # upstreamed. + "//patches:0014-openroad-ram-reset.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0014-openroad-ram-reset.patch b/patches/0014-openroad-ram-reset.patch new file mode 100644 index 000000000..4092650d2 --- /dev/null +++ b/patches/0014-openroad-ram-reset.patch @@ -0,0 +1,1342 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -reset_value, an asynchronous reset + +-reset_value v resets every word to v asynchronously. Each bit's flop is +cleared or preset by the reset, the other pin held off by one tie cell +per word slice: the data, clear and preset pins are read from the flop's +ff group, and which pin gives which value accounts for the flop's +output polarity (asap7's DFFASRHQNx1 stores !D, so its `clear` sets the +data to 1). The reset port takes the flop's own polarity, rst_n or rst; +a parent adapts any other reset, or a synchronous one, to it. The +storage cell, found or given, has both a clear and a preset. The +behavioral model resets the same way. Not with -use_latch (RAM-0065). + +Several ORFS designs reset their register files (ibex, whose ECC and +lockstep checks need valid codewords from the first cycle; cva6, +ariane, swerv, coralnpu); it is an option, off by default. + +The fourth of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index c73f269d6c..7fbfe970a5 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -45,6 +45,7 @@ generate_ram [-mask_size bits] + [-tristate_cell name] + [-read_style tristate|and_or] + [-zero_word word] ++ [-reset_value value] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -72,6 +73,7 @@ generate_ram [-mask_size bits] + | `-tristate_cell` | Name of the master to use for the tristate device (i.e. a tristate inverter). It is currently assumed that the device is inverting. Default: auto-select from the loaded cell library. | + | `-read_style` | The read path: `tristate`, a tristate bitline per bit, or `and_or`, a tree per bit column of an AOI22 over each pair of rows and NAND2 and NOR2 levels above, for a library without a tristate cell. `and_or` also takes a storage flop whose only output is inverted (QN). Default: `tristate` where the library has a tristate cell, `and_or` where it has none. | + | `-zero_word` | A word that reads 0 and drops its writes, as a RISC-V register file's x0: its row has no flops or clock gate, and the read trees leave it out. Needs `-read_style and_or` and `-column_mux_ratio 1`. Default: none. | ++| `-reset_value` | Resets every word to `value` asynchronously, through a reset port at the storage flop's own polarity (`rst_n` or `rst`); each bit's flop is cleared or preset, the other pin held off. The storage cell has both an asynchronous clear and preset. A parent adapts a reset of another polarity, or a synchronous one, to it. Not with `-use_latch`. Default: no reset. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index e7fc10c122..0f332d5097 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -111,7 +111,8 @@ class RamGen + odb::dbMaster* tapcell, + int max_tap_dist, + const std::string& read_style = "", +- int zero_word = -1); ++ int zero_word = -1, ++ const std::string& reset_value = ""); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -167,6 +168,10 @@ class RamGen + const std::vector& selects, + odb::dbNet* out); + bool treeInverted(int lo, int hi) const; ++ // -reset_value: the storage flop's data, clear and preset pins, the ++ // reset's polarity, what a cleared flop reads, and the tie cell that ++ // holds the unused pin off ++ void findResetPins(); + // The smallest cell `match` accepts; none is an error unless not + // `required`, then nullptr. + odb::dbMaster* findMaster(const std::function& match, +@@ -193,7 +198,9 @@ class RamGen + std::vector& select, + odb::dbNet* data_input, + std::vector& data_output, +- odb::dbNet* storage_net = nullptr); ++ odb::dbNet* storage_net = nullptr, ++ int reset_bit = -1, ++ odb::dbNet* reset_off = nullptr); + void makeSlice(int slice_idx, + int mask_size, + int row_idx, +@@ -315,6 +322,20 @@ class RamGen + std::string read_style_; + bool storage_inverted_{false}; // the storage flop's output is QN + int zero_word_{-1}; // the word that reads 0 and is not stored, or -1 ++ // An asynchronous reset to reset_value_ (a word's value, every word): ++ // each bit's flop is cleared or preset by the reset port, the other ++ // pin held off. The pins come from the flop's ff group; clear_reads_ ++ // is the data a cleared flop reads back, after any inversion. ++ std::string reset_value_; ++ uint64_t reset_bits_{0}; ++ odb::dbBTerm* reset_port_{nullptr}; ++ odb::dbMaster* tie_off_cell_{nullptr}; // drives the inactive level ++ std::string tie_off_pin_; ++ std::string storage_data_pin_; ++ std::string storage_clear_pin_; ++ std::string storage_preset_pin_; ++ bool reset_active_low_{true}; ++ int clear_reads_{0}; + // per (row, word in the row, bit): the storage net, and the tree + // cells placed in that bit's cell + std::map, odb::dbNet*> storage_nets_; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 7362a35c8e..a6481b09fd 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -116,7 +116,9 @@ std::unique_ptr RamGen::makeBit(const std::string& prefix, + vector& select, + dbNet* data_input, + vector& data_output, +- dbNet* storage_net) ++ dbNet* storage_net, ++ const int reset_bit, ++ dbNet* reset_off) + { + auto bit_cell = std::make_unique(); + +@@ -126,13 +128,19 @@ std::unique_ptr RamGen::makeBit(const std::string& prefix, + } + + if (!use_latch_) { +- makeInst(bit_cell.get(), +- prefix, +- "bit", +- storage_cell_, +- {{storage_ports_[{PortRoleType::Clock, 0}], clock}, +- {storage_ports_[{PortRoleType::DataIn, 0}], data_input}, +- {storage_ports_[{PortRoleType::DataOut, 0}], storage_net}}); ++ vector> conns ++ = {{storage_ports_[{PortRoleType::Clock, 0}], clock}, ++ {storage_ports_[{PortRoleType::DataIn, 0}], data_input}, ++ {storage_ports_[{PortRoleType::DataOut, 0}], storage_net}}; ++ if (reset_bit >= 0) { ++ // the reset clears the flop where a cleared flop reads the bit's ++ // value, else presets it; the other pin held off ++ dbNet* reset = reset_port_->getNet(); ++ const bool clear = reset_bit == clear_reads_; ++ conns.emplace_back(storage_clear_pin_, clear ? reset : reset_off); ++ conns.emplace_back(storage_preset_pin_, clear ? reset_off : reset); ++ } ++ makeInst(bit_cell.get(), prefix, "bit", storage_cell_, conns); + } else { + makeInst(bit_cell.get(), + prefix, +@@ -336,6 +344,17 @@ void RamGen::makeSlice(const int slice_idx, + auto we_net = makeNet(prefix, "we"); + auto sel_cell = std::make_unique(); + ++ // -reset_value: one tie per word slice holds the flops' unused pins off ++ dbNet* reset_off = nullptr; ++ if (reset_port_) { ++ reset_off = makeNet(prefix, "reset_off"); ++ makeInst(sel_cell.get(), ++ prefix, ++ "reset_tie", ++ tie_off_cell_, ++ {{tie_off_pin_, reset_off}}); ++ } ++ + // More than one write port: port w writes this word when its row select + // and its write enable are both high (we{w}), and its data is taken + // unless a later port writes the word in the same cycle (take{w}): the +@@ -398,15 +417,21 @@ void RamGen::makeSlice(const int slice_idx, + d = makeNet(name, "d"); + } + const int bit = start_bit_idx + local_bit; +- auto bit_cell = and_or_read_ +- ? makeBit(name, +- 0, +- gclock_net, +- select_b_nets, +- d, +- outs, +- storage_nets_.at({row_idx, word_idx, bit})) +- : makeBit(name, r_total, gclock_net, select_b_nets, d, outs); ++ const int reset_bit ++ = reset_port_ ? (bit < 64 ? static_cast((reset_bits_ >> bit) & 1) ++ : 0) ++ : -1; ++ auto bit_cell ++ = makeBit(name, ++ and_or_read_ ? 0 : r_total, ++ gclock_net, ++ select_b_nets, ++ d, ++ outs, ++ and_or_read_ ? storage_nets_.at({row_idx, word_idx, bit}) ++ : nullptr, ++ reset_bit, ++ reset_off); + if (and_or_read_) { + for (const auto& node : tree_nodes_[{row_idx, word_idx, bit}]) { + makeInst(bit_cell.get(), node.prefix, node.name, node.master, node.conns); +@@ -1021,6 +1046,84 @@ static int twoInputTable(sta::LibertyPort* out) + return table; + } + ++void RamGen::findResetPins() ++{ ++ auto liberty = network_->libertyCell(network_->dbToSta(storage_cell_)); ++ const sta::Sequential* seq = nullptr; ++ for (const auto& s : liberty->sequentials()) { ++ if (s.isRegister() && s.clear() && s.preset()) { ++ seq = &s; ++ break; ++ } ++ } ++ if (!seq) { ++ logger_->error(RAM, ++ 61, ++ "Storage cell {} has no asynchronous clear and preset for " ++ "-reset_value.", ++ storage_cell_->getName()); ++ } ++ // a pin of the ff group, and whether it acts low: "!RN" or "RN" ++ auto pin = [&](const sta::FuncExpr* e, bool& low) -> std::string { ++ low = e->op() == sta::FuncExpr::Op::not_; ++ const sta::FuncExpr* p = low ? e->left() : e; ++ if (p->op() != sta::FuncExpr::Op::port) { ++ logger_->error(RAM, ++ 62, ++ "Storage cell {}: a clear, preset or data that is not " ++ "one pin is not supported.", ++ storage_cell_->getName()); ++ } ++ return p->port()->name(); ++ }; ++ bool clear_low = false; ++ bool preset_low = false; ++ bool data_inverted = false; ++ storage_clear_pin_ = pin(seq->clear(), clear_low); ++ storage_preset_pin_ = pin(seq->preset(), preset_low); ++ storage_data_pin_ = pin(seq->data(), data_inverted); ++ if (clear_low != preset_low) { ++ logger_->error(RAM, ++ 63, ++ "Storage cell {}: clear and preset act on opposite levels.", ++ storage_cell_->getName()); ++ } ++ reset_active_low_ = clear_low; ++ storage_ports_[{PortRoleType::DataIn, 0}] = storage_data_pin_; ++ ++ // A clear sets the ff group's first state variable to 0; the output ++ // pin reads it or its complement, and the data read back is that, ++ // inverted again where the storage output is (asap7's DFFASRHQNx1 ++ // stores !D: its `clear` sets the data to 1). ++ auto out = liberty->findLibertyPort( ++ storage_ports_[{PortRoleType::DataOut, 0}].c_str()); ++ bool reads_complement = false; ++ if (out && out->function() ++ && out->function()->op() == sta::FuncExpr::Op::port) { ++ reads_complement = seq->outputInv() == out->function()->port(); ++ } ++ clear_reads_ = (reads_complement ? 1 : 0) ^ (storage_inverted_ ? 1 : 0); ++ ++ // the unused pin of each flop held at its inactive level ++ const bool off_high = reset_active_low_; ++ tie_off_cell_ = findMaster( ++ [off_high](sta::LibertyPort* port) { ++ auto f = port->function(); ++ return f && port->direction()->isOutput() ++ && f->op() ++ == (off_high ? sta::FuncExpr::Op::one ++ : sta::FuncExpr::Op::zero); ++ }, ++ off_high ? "tie high" : "tie low"); ++ tie_off_pin_ = buildPortMap(tie_off_cell_)[{PortRoleType::DataOut, 0}]; ++ ++ try { ++ reset_bits_ = std::stoull(reset_value_, nullptr, 0); ++ } catch (const std::exception&) { ++ logger_->error(RAM, 64, "-reset_value {} is not a number.", reset_value_); ++ } ++} ++ + void RamGen::findMasters() + { + if (!inv_cell_) { +@@ -1076,11 +1179,24 @@ void RamGen::findMasters() + if (!storage_cell_) { + // FIXME + // Still needs changes to get right type of flip-flop ++ const bool reset = !reset_value_.empty(); + storage_cell_ = findMaster( +- [](sta::LibertyPort* port) { ++ [reset](sta::LibertyPort* port) { + if (!port->isRegOutput()) { + return false; + } ++ // with a reset, a flop with both an asynchronous clear and ++ // preset, so any bit can take either value ++ if (reset) { ++ bool clear_preset = false; ++ for (const auto& seq : port->libertyCell()->sequentials()) { ++ clear_preset ++ |= seq.isRegister() && seq.clear() && seq.preset(); ++ } ++ if (!clear_preset) { ++ return false; ++ } ++ } + // looking for DFF specifically + auto cell = port->libertyCell(); + auto port_iter = cell->portIterator(); +@@ -1109,6 +1225,9 @@ void RamGen::findMasters() + "-read_style and_or.", + storage_cell_->getName()); + } ++ if (!reset_value_.empty()) { ++ findResetPins(); ++ } + } + + if (!clock_gate_cell_) { +@@ -1558,7 +1677,8 @@ void RamGen::generate(const int mask_size, + dbMaster* tapcell, + int max_tap_dist, + const std::string& read_style, +- const int zero_word) ++ const int zero_word, ++ const std::string& reset_value) + { + if (num_words / column_mux_ratio == 1) { + logger_->error(RAM, 42, "1-row RAMs are not supported."); +@@ -1607,6 +1727,9 @@ void RamGen::generate(const int mask_size, + num_write_ = rw_ports + w_ports; + read_style_ = read_style; + zero_word_ = zero_word; ++ reset_value_ = reset_value; ++ reset_port_ = nullptr; ++ tie_off_cell_ = nullptr; + and_or_read_ = false; + storage_inverted_ = false; + storage_nets_.clear(); +@@ -1702,6 +1825,16 @@ void RamGen::generate(const int mask_size, + + auto clock = makeBTerm("clk", dbIoType::INPUT); + ++ // -reset_value: an asynchronous reset at the storage flop's own ++ // polarity, rst_n or rst; a parent adapts any other reset to it ++ if (!reset_value_.empty()) { ++ if (use_latch_) { ++ logger_->error(RAM, 65, "-reset_value is not supported with -use_latch."); ++ } ++ reset_port_ = makeBTerm(reset_active_low_ ? "rst_n" : "rst", ++ dbIoType::INPUT); ++ } ++ + // One write enable bus per write port: we, or with more than one write + // port we0, we1, ... + const int num_write = num_write_; +@@ -2449,6 +2582,12 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + }; + // Build port list + std::string port_list = "\n clk"; ++ // -reset_value: the reset port, at the storage flop's polarity ++ const std::string reset_name ++ = reset_value_.empty() ? "" : (reset_active_low_ ? "rst_n" : "rst"); ++ if (!reset_name.empty()) { ++ port_list += ",\n " + reset_name; ++ } + for (int w = 0; w < num_write; ++w) { + port_list += ",\n " + wbus("D", w); + } +@@ -2570,17 +2709,37 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + mask_size); + } + ++ std::string reset_declaration; ++ std::string always_head = " always @(posedge clk) begin\n"; ++ if (!reset_name.empty()) { ++ reset_declaration = fmt::format(" input {};\n", reset_name); ++ always_head = fmt::format( ++ " always @(posedge clk or {}edge {}) begin\n" ++ " if ({}{}) begin\n" ++ " for (i = 0; i < {}; i = i + 1) begin\n" ++ " mem[i] <= {}'d{};\n" ++ " end\n" ++ " end else begin\n", ++ reset_active_low_ ? "neg" : "pos", ++ reset_name, ++ reset_active_low_ ? "!" : "", ++ reset_name, ++ num_words, ++ word_size_bit, ++ reset_bits_); ++ write_logic += " end\n"; ++ } ++ + std::string verilog_code = fmt::format(R"(module {} ({} + ); + input clk; +-{}{}{}{} ++{}{}{}{}{} + // memory array declaration + reg [{}:0] mem[0:{}]; + + // write logic + integer i; +- always @(posedge clk) begin +-{} end ++{}{} end + + // read logic + {} +@@ -2588,12 +2747,14 @@ endmodule + )", + module_name, + port_list, ++ reset_declaration, + data_declarations, + output_declaration, + addr_declarations, + enable_declarations, + word_size_bit - 1, + num_words - 1, ++ always_head, + write_logic, + read_port_logic); + +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 5f765b215b..9ccfcf5790 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -44,7 +44,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* tapcell_name, + const int max_tap_dist, + const char* read_style, +- const int zero_word) ++ const int zero_word, ++ const char* reset_value) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -96,7 +97,8 @@ generate_ram_netlist_cmd(int mask_size, + + ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, +- tapcell, max_tap_dist, read_style, zero_word); ++ tapcell, max_tap_dist, read_style, zero_word, ++ reset_value); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 998f61fde5..6d41e0bda8 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -9,7 +9,9 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-tristate_cell name] + [-read_style tristate|and_or] + [-zero_word word] ++ [-reset_value value] + [-zero_word word] ++ [-reset_value value] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -22,7 +24,7 @@ proc generate_ram_netlist { args } { + sta::parse_key_args "generate_ram_netlist" args \ + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist +- -write_behavioral_verilog -read_style -zero_word } flags {} ++ -write_behavioral_verilog -read_style -zero_word -reset_value } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -152,9 +154,15 @@ proc generate_ram_netlist { args } { + set zero_word $keys(-zero_word) + } + ++ # An asynchronous reset of every word to this value. ++ set reset_value "" ++ if { [info exists keys(-reset_value)] } { ++ set reset_value $keys(-reset_value) ++ } ++ + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ +- $read_style $zero_word ++ $read_style $zero_word $reset_value + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -188,7 +196,7 @@ proc generate_ram { args } { + -r_ports -w_ports -use_latch -power_net_name + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist +- -write_behavioral_verilog -read_style -zero_word } flags {} ++ -write_behavioral_verilog -read_style -zero_word -reset_value } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -233,6 +241,10 @@ proc generate_ram { args } { + lappend ram_netlist_args -zero_word $keys(-zero_word) + } + ++ if { [info exists keys(-reset_value)] } { ++ lappend ram_netlist_args -reset_value $keys(-reset_value) ++ } ++ + if { [info exists keys(-inv_cell)] } { + lappend ram_netlist_args -inv_cell $keys(-inv_cell) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 0bd0331ed9..b964c56b3b 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_2r1w_reset_asap7", + "make_8x8_2r1w_zero_asap7", + "make_8x8_2r1w_and_or_asap7", + "make_7x7_1r2w_nangate45", +@@ -98,6 +99,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_zero_asap7_behavioral.vok", + ], ++ "make_8x8_2r1w_reset_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_reset_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_reset_asap7.defok b/src/ram/test/make_8x8_2r1w_reset_asap7.defok +new file mode 100644 +index 0000000000..24d4aea460 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_reset_asap7.defok +@@ -0,0 +1,706 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 2079 243 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 385 BY 1 STEP 5 0 ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 385 BY 1 STEP 5 0 ; ++COMPONENTS 289 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 216 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 205 216 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 410 216 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 615 216 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 820 216 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1026 216 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1231 216 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 1436 216 ) N ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1809 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1809 27 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1809 54 ) N ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1809 81 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1809 108 ) N ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1809 135 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1809 162 ) N ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1809 189 ) FS ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1841 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1841 27 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1841 54 ) N ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1841 81 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1841 108 ) N ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1841 135 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1841 162 ) N ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1841 189 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 2046 108 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 2046 54 ) N ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 2046 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1895 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1895 27 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1895 54 ) N ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1895 81 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1895 108 ) N ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1895 135 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1895 162 ) N ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1895 189 ) FS ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1927 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1927 27 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1927 54 ) N ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1927 81 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1927 108 ) N ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1927 135 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1927 162 ) N ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1927 189 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 2046 135 ) FS ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 2046 81 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 2046 27 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1981 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1981 27 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1981 54 ) N ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1981 81 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1981 108 ) N ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1981 135 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1981 162 ) N ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1981 189 ) FS ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2014 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2014 27 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2014 54 ) N ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2014 81 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2014 108 ) N ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2014 135 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2014 162 ) N ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2014 189 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 2062 108 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 2062 54 ) N ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 2062 0 ) N ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 140 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 140 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 140 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 140 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 140 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 345 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 345 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 550 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 550 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 550 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 550 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 550 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 550 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 550 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 756 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 756 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 756 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 756 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 756 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 756 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 756 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 961 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 961 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 961 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 961 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 961 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 961 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 961 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1166 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1166 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1166 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1166 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1166 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1371 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1371 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1371 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1576 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1576 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1576 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1576 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1576 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1576 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1576 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 162 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 162 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 162 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 378 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 378 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 378 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 378 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 367 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 367 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 367 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 583 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 583 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 583 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 583 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 572 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 572 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 572 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 788 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 788 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 788 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 788 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 777 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 777 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 777 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 993 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 993 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 993 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 993 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 982 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 982 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 982 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1188 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1188 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1188 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1393 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1393 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1393 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1609 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1609 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1609 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1609 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1598 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1598 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1598 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1873 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1873 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1873 54 ) N ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1873 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1873 108 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1873 135 ) FS ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1873 162 ) N ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1873 189 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1960 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1960 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1960 54 ) N ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1960 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1960 108 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1960 135 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1960 162 ) N ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1960 189 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1787 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1787 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1787 54 ) N ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1787 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1787 108 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1787 135 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1787 162 ) N ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1787 189 ) FS ; ++ - storage_0_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - storage_0_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 0 ) N ; ++ - storage_0_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 0 ) N ; ++ - storage_0_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 0 ) N ; ++ - storage_0_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 0 ) N ; ++ - storage_0_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 0 ) N ; ++ - storage_0_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 0 ) N ; ++ - storage_0_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 0 ) N ; ++ - storage_0_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 0 ) N ; ++ - storage_0_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 0 ) N ; ++ - storage_0_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 27 ) FS ; ++ - storage_1_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 54 ) N ; ++ - storage_2_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 81 ) FS ; ++ - storage_3_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 81 ) FS ; ++ - storage_4_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 108 ) N ; ++ - storage_4_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 108 ) N ; ++ - storage_4_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 108 ) N ; ++ - storage_4_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 108 ) N ; ++ - storage_5_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 135 ) FS ; ++ - storage_5_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 135 ) FS ; ++ - storage_5_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 135 ) FS ; ++ - storage_5_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 135 ) FS ; ++ - storage_6_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 162 ) N ; ++ - storage_6_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 162 ) N ; ++ - storage_6_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 162 ) N ; ++ - storage_6_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 162 ) N ; ++ - storage_7_0_0.bit0.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 205 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 410 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 615 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 820 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1026 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1231 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFASRHQNx1_ASAP7_75t_R + PLACED ( 1436 189 ) FS ; ++ - storage_7_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1657 189 ) FS ; ++ - storage_7_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1755 189 ) FS ; ++ - storage_7_0_0.reset_tie TIEHIx1_ASAP7_75t_R + PLACED ( 1641 189 ) FS ; ++END COMPONENTS ++PINS 36 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - rst_n + NET rst_n + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 309 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_7_0_0.bit0.bit D ) ( storage_6_0_0.bit0.bit D ) ( storage_5_0_0.bit0.bit D ) ( storage_4_0_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ++ ( storage_1_0_0.bit0.bit D ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_7_0_0.bit1.bit D ) ( storage_6_0_0.bit1.bit D ) ( storage_5_0_0.bit1.bit D ) ( storage_4_0_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ++ ( storage_1_0_0.bit1.bit D ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_7_0_0.bit2.bit D ) ( storage_6_0_0.bit2.bit D ) ( storage_5_0_0.bit2.bit D ) ( storage_4_0_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ++ ( storage_1_0_0.bit2.bit D ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_7_0_0.bit3.bit D ) ( storage_6_0_0.bit3.bit D ) ( storage_5_0_0.bit3.bit D ) ( storage_4_0_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ++ ( storage_1_0_0.bit3.bit D ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_7_0_0.bit4.bit D ) ( storage_6_0_0.bit4.bit D ) ( storage_5_0_0.bit4.bit D ) ( storage_4_0_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ++ ( storage_1_0_0.bit4.bit D ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_7_0_0.bit5.bit D ) ( storage_6_0_0.bit5.bit D ) ( storage_5_0_0.bit5.bit D ) ( storage_4_0_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ++ ( storage_1_0_0.bit5.bit D ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_7_0_0.bit6.bit D ) ( storage_6_0_0.bit6.bit D ) ( storage_5_0_0.bit6.bit D ) ( storage_4_0_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ++ ( storage_1_0_0.bit6.bit D ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_7_0_0.bit7.bit D ) ( storage_6_0_0.bit7.bit D ) ( storage_5_0_0.bit7.bit D ) ( storage_4_0_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ++ ( storage_1_0_0.bit7.bit D ) ( storage_0_0_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.cg CLK ) ( storage_6_0_0.cg CLK ) ( storage_5_0_0.cg CLK ) ( storage_4_0_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_0_0.cg CLK ) ++ ( storage_1_0_0.cg CLK ) ( storage_0_0_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A1 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A1 ) ++ ( read_w0_p0_b1.aoi_r0 A1 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A1 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A1 ) ++ ( read_w0_p1_b1.aoi_r0 A1 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - rst_n ( PIN rst_n ) ( storage_7_0_0.bit7.bit SETN ) ( storage_7_0_0.bit6.bit RESETN ) ( storage_7_0_0.bit5.bit SETN ) ( storage_7_0_0.bit4.bit RESETN ) ( storage_7_0_0.bit3.bit RESETN ) ( storage_7_0_0.bit2.bit SETN ) ++ ( storage_7_0_0.bit1.bit RESETN ) ( storage_7_0_0.bit0.bit SETN ) ( storage_6_0_0.bit7.bit SETN ) ( storage_6_0_0.bit6.bit RESETN ) ( storage_6_0_0.bit5.bit SETN ) ( storage_6_0_0.bit4.bit RESETN ) ( storage_6_0_0.bit3.bit RESETN ) ( storage_6_0_0.bit2.bit SETN ) ++ ( storage_6_0_0.bit1.bit RESETN ) ( storage_6_0_0.bit0.bit SETN ) ( storage_5_0_0.bit7.bit SETN ) ( storage_5_0_0.bit6.bit RESETN ) ( storage_5_0_0.bit5.bit SETN ) ( storage_5_0_0.bit4.bit RESETN ) ( storage_5_0_0.bit3.bit RESETN ) ( storage_5_0_0.bit2.bit SETN ) ++ ( storage_5_0_0.bit1.bit RESETN ) ( storage_5_0_0.bit0.bit SETN ) ( storage_4_0_0.bit7.bit SETN ) ( storage_4_0_0.bit6.bit RESETN ) ( storage_4_0_0.bit5.bit SETN ) ( storage_4_0_0.bit4.bit RESETN ) ( storage_4_0_0.bit3.bit RESETN ) ( storage_4_0_0.bit2.bit SETN ) ++ ( storage_4_0_0.bit1.bit RESETN ) ( storage_4_0_0.bit0.bit SETN ) ( storage_3_0_0.bit7.bit SETN ) ( storage_3_0_0.bit6.bit RESETN ) ( storage_3_0_0.bit5.bit SETN ) ( storage_3_0_0.bit4.bit RESETN ) ( storage_3_0_0.bit3.bit RESETN ) ( storage_3_0_0.bit2.bit SETN ) ++ ( storage_3_0_0.bit1.bit RESETN ) ( storage_3_0_0.bit0.bit SETN ) ( storage_2_0_0.bit7.bit SETN ) ( storage_2_0_0.bit6.bit RESETN ) ( storage_2_0_0.bit5.bit SETN ) ( storage_2_0_0.bit4.bit RESETN ) ( storage_2_0_0.bit3.bit RESETN ) ( storage_2_0_0.bit2.bit SETN ) ++ ( storage_2_0_0.bit1.bit RESETN ) ( storage_2_0_0.bit0.bit SETN ) ( storage_1_0_0.bit7.bit SETN ) ( storage_1_0_0.bit6.bit RESETN ) ( storage_1_0_0.bit5.bit SETN ) ( storage_1_0_0.bit4.bit RESETN ) ( storage_1_0_0.bit3.bit RESETN ) ( storage_1_0_0.bit2.bit SETN ) ++ ( storage_1_0_0.bit1.bit RESETN ) ( storage_1_0_0.bit0.bit SETN ) ( storage_0_0_0.bit7.bit SETN ) ( storage_0_0_0.bit6.bit RESETN ) ( storage_0_0_0.bit5.bit SETN ) ( storage_0_0_0.bit4.bit RESETN ) ( storage_0_0_0.bit3.bit RESETN ) ( storage_0_0_0.bit2.bit SETN ) ++ ( storage_0_0_0.bit1.bit RESETN ) ( storage_0_0_0.bit0.bit SETN ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.storage ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A2 ) ( storage_0_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.storage ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( storage_0_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.storage ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( storage_0_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.storage ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( storage_0_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.storage ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A2 ) ( storage_0_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.storage ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( storage_0_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.storage ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( storage_0_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.storage ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A2 ) ( storage_0_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.gclock ( storage_0_0_0.cg GCLK ) ( storage_0_0_0.bit7.bit CLK ) ( storage_0_0_0.bit6.bit CLK ) ( storage_0_0_0.bit5.bit CLK ) ( storage_0_0_0.bit4.bit CLK ) ( storage_0_0_0.bit3.bit CLK ) ( storage_0_0_0.bit2.bit CLK ) ++ ( storage_0_0_0.bit1.bit CLK ) ( storage_0_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_0_0.reset_off ( storage_0_0_0.bit7.bit RESETN ) ( storage_0_0_0.bit6.bit SETN ) ( storage_0_0_0.bit5.bit RESETN ) ( storage_0_0_0.bit4.bit SETN ) ( storage_0_0_0.bit3.bit SETN ) ( storage_0_0_0.bit2.bit RESETN ) ( storage_0_0_0.bit1.bit SETN ) ++ ( storage_0_0_0.bit0.bit RESETN ) ( storage_0_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_0_0_0.we ( storage_0_0_0.gcand Y ) ( storage_0_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.reset_off ( storage_1_0_0.bit7.bit RESETN ) ( storage_1_0_0.bit6.bit SETN ) ( storage_1_0_0.bit5.bit RESETN ) ( storage_1_0_0.bit4.bit SETN ) ( storage_1_0_0.bit3.bit SETN ) ( storage_1_0_0.bit2.bit RESETN ) ( storage_1_0_0.bit1.bit SETN ) ++ ( storage_1_0_0.bit0.bit RESETN ) ( storage_1_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.reset_off ( storage_2_0_0.bit7.bit RESETN ) ( storage_2_0_0.bit6.bit SETN ) ( storage_2_0_0.bit5.bit RESETN ) ( storage_2_0_0.bit4.bit SETN ) ( storage_2_0_0.bit3.bit SETN ) ( storage_2_0_0.bit2.bit RESETN ) ( storage_2_0_0.bit1.bit SETN ) ++ ( storage_2_0_0.bit0.bit RESETN ) ( storage_2_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.reset_off ( storage_3_0_0.bit7.bit RESETN ) ( storage_3_0_0.bit6.bit SETN ) ( storage_3_0_0.bit5.bit RESETN ) ( storage_3_0_0.bit4.bit SETN ) ( storage_3_0_0.bit3.bit SETN ) ( storage_3_0_0.bit2.bit RESETN ) ( storage_3_0_0.bit1.bit SETN ) ++ ( storage_3_0_0.bit0.bit RESETN ) ( storage_3_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.gclock ( storage_4_0_0.cg GCLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_4_0_0.reset_off ( storage_4_0_0.bit7.bit RESETN ) ( storage_4_0_0.bit6.bit SETN ) ( storage_4_0_0.bit5.bit RESETN ) ( storage_4_0_0.bit4.bit SETN ) ( storage_4_0_0.bit3.bit SETN ) ( storage_4_0_0.bit2.bit RESETN ) ( storage_4_0_0.bit1.bit SETN ) ++ ( storage_4_0_0.bit0.bit RESETN ) ( storage_4_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.gcand Y ) ( storage_4_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.gclock ( storage_5_0_0.cg GCLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_5_0_0.reset_off ( storage_5_0_0.bit7.bit RESETN ) ( storage_5_0_0.bit6.bit SETN ) ( storage_5_0_0.bit5.bit RESETN ) ( storage_5_0_0.bit4.bit SETN ) ( storage_5_0_0.bit3.bit SETN ) ( storage_5_0_0.bit2.bit RESETN ) ( storage_5_0_0.bit1.bit SETN ) ++ ( storage_5_0_0.bit0.bit RESETN ) ( storage_5_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.gcand Y ) ( storage_5_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.gclock ( storage_6_0_0.cg GCLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_6_0_0.reset_off ( storage_6_0_0.bit7.bit RESETN ) ( storage_6_0_0.bit6.bit SETN ) ( storage_6_0_0.bit5.bit RESETN ) ( storage_6_0_0.bit4.bit SETN ) ( storage_6_0_0.bit3.bit SETN ) ( storage_6_0_0.bit2.bit RESETN ) ( storage_6_0_0.bit1.bit SETN ) ++ ( storage_6_0_0.bit0.bit RESETN ) ( storage_6_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.gcand Y ) ( storage_6_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.gclock ( storage_7_0_0.cg GCLK ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_7_0_0.reset_off ( storage_7_0_0.bit7.bit RESETN ) ( storage_7_0_0.bit6.bit SETN ) ( storage_7_0_0.bit5.bit RESETN ) ( storage_7_0_0.bit4.bit SETN ) ( storage_7_0_0.bit3.bit SETN ) ( storage_7_0_0.bit2.bit RESETN ) ( storage_7_0_0.bit1.bit SETN ) ++ ( storage_7_0_0.bit0.bit RESETN ) ( storage_7_0_0.reset_tie H ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.gcand Y ) ( storage_7_0_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) ( storage_0_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_7_0_0.gcand B ) ( storage_6_0_0.gcand B ) ( storage_5_0_0.gcand B ) ( storage_4_0_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_0_0.gcand B ) ++ ( storage_1_0_0.gcand B ) ( storage_0_0_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_reset_asap7.tcl b/src/ram/test/make_8x8_2r1w_reset_asap7.tcl +new file mode 100644 +index 0000000000..627b544716 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_reset_asap7.tcl +@@ -0,0 +1,33 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees, and every word resets to 0xa5 asynchronously: the flop ++# stores !D, so its clear sets a 1. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_reset_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFASRHQNx1_ASAP7_75t_R \ ++ -reset_value 0xa5 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_reset_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_reset_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_reset_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_reset_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_reset_asap7_behavioral.vok +new file mode 100644 +index 0000000000..a0213ab892 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_reset_asap7_behavioral.vok +@@ -0,0 +1,50 @@ ++module RAM8x8 ( ++ clk, ++ rst_n, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input rst_n; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk or negedge rst_n) begin ++ if (!rst_n) begin ++ for (i = 0; i < 8; i = i + 1) begin ++ mem[i] <= 8'd165; ++ end ++ end else begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i]) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index ad53c742b5..ccfe40b181 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -8,5 +8,6 @@ record_tests { + make_7x7_1r2w_nangate45 + make_8x8_2r1w_and_or_asap7 + make_8x8_2r1w_zero_asap7 ++ make_8x8_2r1w_reset_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 4dbbc25c9..8342b9244 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -175,6 +175,7 @@ test_suite( "@openroad//src/ram/test:make_7x7_2r1w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_and_or_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_reset_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_sky130-tcl_test", diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index aade170a6..99d0b2810 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -155,7 +155,9 @@ ASAP7 = { # Nangate45's tristate bitlines (patch 0011), its AND-OR trees asked for # (patch 0012), and asap7's, which has no tristate cell, with its QN-only # flop (the storage cell named: the smallest flop is negative-edge), and -# with a word reading 0 (patch 0013), on either polarity of flop. +# with a word reading 0 (patch 0013), on either polarity of flop; and +# with an asynchronous reset to a value of both 0s and 1s (patch 0014), +# on Nangate45's set/reset flop and asap7's, which stores !D. [ [ genrule( @@ -193,7 +195,7 @@ sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_g verilog_library( name = "tb_%s_rtl" % name, srcs = [ - "tb_ram_2w.v", + "%s.v" % tb, ":%s_gen.v" % name, ":%s_model.v" % name, ] + platform["stdcell"], @@ -201,7 +203,7 @@ sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_g verilator_cc_library( name = "tb_%s" % name, module = ":tb_%s_rtl" % name, - module_top = "tb_ram_2w", + module_top = tb, trace_mode = "none", vopts = [ "-Wno-fatal", @@ -212,15 +214,18 @@ sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_g cc_test( name = "%s_sim_test" % name, size = "small", - srcs = ["tb_ram_2w.cc"], + srcs = ["%s.cc" % tb], deps = [":tb_%s" % name], ), ] - for name, platform, args in [ - ("ram_2w", NANGATE45, "-storage_cell DFF_X1"), - ("ram_2w_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or"), - ("ram_2w_and_or_zero", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -zero_word 3"), - ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R"), - ("ram_2w_asap7_zero", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -zero_word 0"), + for name, platform, args, tb in [ + ("ram_2w", NANGATE45, "-storage_cell DFF_X1", "tb_ram_2w"), + ("ram_2w_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or", "tb_ram_2w"), + ("ram_2w_and_or_zero", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -zero_word 3", "tb_ram_2w"), + ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R", "tb_ram_2w"), + ("ram_2w_asap7_zero", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -zero_word 0", "tb_ram_2w"), + ("ram_2w_rst", NANGATE45, "-storage_cell DFFRS_X1 -reset_value 0xa5", "tb_ram_2w_rst"), + ("ram_2w_rst_and_or", NANGATE45, "-storage_cell DFFRS_X1 -read_style and_or -reset_value 0xa5", "tb_ram_2w_rst"), + ("ram_2w_rst_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -reset_value 0xa5", "tb_ram_2w_rst"), ] ] diff --git a/test/regfile/sim/tb_ram_2w_rst.cc b/test/regfile/sim/tb_ram_2w_rst.cc new file mode 100644 index 000000000..fcb6b6b5c --- /dev/null +++ b/test/regfile/sim/tb_ram_2w_rst.cc @@ -0,0 +1,64 @@ +// generate_ram's two-write RAM with -reset_value 0xa5: after a reset +// every word reads 0xa5 on both the netlist and the behavioral model; +// then random writes on both ports, a quarter to the same word, with an +// asynchronous reset now and then, a read compared every cycle. +#include +#include +#include + +#include "Vtb_ram_2w_rst.h" + +int main() { + Vtb_ram_2w_rst tb; + std::mt19937 rng(1); + int bad = 0; + int cycle = 0; + auto compare = [&](int ra) { + tb.addr_r0 = ra; + tb.eval(); + if (tb.Q_model != tb.Q_gen) { + std::printf("cycle %d: read %d: model %02x, generated %02x\n", cycle, + ra, tb.Q_model, tb.Q_gen); + ++bad; + } + }; + auto reset = [&]() { + tb.clk = 0; + tb.we0 = 0; + tb.we1 = 0; + tb.rst_n = 0; + tb.eval(); + tb.rst_n = 1; + tb.eval(); + for (int w = 0; w < 8; ++w) { + compare(w); + if (tb.Q_model != 0xa5) { + std::printf("cycle %d: word %d after reset: model %02x\n", cycle, w, + tb.Q_model); + ++bad; + } + } + }; + tb.rst_n = 1; + tb.clk = 0; + tb.eval(); + reset(); + for (int i = 0; i < 20000 && bad < 10; ++i, ++cycle) { + if (rng() % 500 == 0) { + reset(); + } + const int a0 = rng() % 8; + tb.clk = 0; + tb.we0 = rng() % 2; + tb.addr_w0 = a0; + tb.D0 = rng() & 0xff; + tb.we1 = rng() % 2; + tb.addr_w1 = rng() % 4 == 0 ? a0 : rng() % 8; + tb.D1 = rng() & 0xff; + compare(rng() % 8); + tb.clk = 1; + tb.eval(); + } + std::printf("%d cycles, %d mismatches\n", cycle, bad); + return bad == 0 ? 0 : 1; +} diff --git a/test/regfile/sim/tb_ram_2w_rst.v b/test/regfile/sim/tb_ram_2w_rst.v new file mode 100644 index 000000000..adff257d2 --- /dev/null +++ b/test/regfile/sim/tb_ram_2w_rst.v @@ -0,0 +1,25 @@ +// generate_ram with two write ports, one read port and an asynchronous +// reset (-reset_value): its behavioral +// model (RAM8x8) and its netlist (RAM8x8_gen) on the same inputs. +module tb_ram_2w_rst ( + input clk, + input rst_n, + input [7:0] D0, + input [7:0] D1, + input [2:0] addr_w0, + input [2:0] addr_w1, + input [2:0] addr_r0, + input we0, + input we1, + output [7:0] Q_model, + output [7:0] Q_gen +); + RAM8x8 model ( + .clk(clk), .rst_n(rst_n), .D0(D0), .D1(D1), .Q(Q_model), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1) + ); + RAM8x8_gen gen ( + .clk(clk), .rst_n(rst_n), .D0(D0), .D1(D1), .Q(Q_gen), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1) + ); +endmodule From 2e0cc86394505ac79070ee1f5e5ec1b71b1abacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 09:00:03 +0200 Subject: [PATCH 14/26] ram: generate_ram -banks, -bank_columns, -bank_order (patch 0015) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fifth generate_regfile feature carried onto generate_ram, on 0014: the words in banks, contiguous or interleaved in the address, some side by side and the rest stacked, as XiangShan's register files ask (224 words in 4 interleaved banks, 2 side by side). With banks each port decodes every word's whole address, an AND2 tree per word, so a bank need not be a power of two words; a read port is one tristate bitline or one AND-OR tree over every word. Without -banks nothing changes. Also gives each inverter column at least one port: an array with fewer rows than address bits had no address inverters at all. Tests: make_8x8_2r1w_banks_asap7 in generate_ram's format; the two-write RAM simulated in five bank shapes, tristate and AND-OR, contiguous and interleaved, side by side and stacked, with a zero word, and 12 words in banks of 3 (the simulation now takes a word count). No mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 4 + patches/0015-openroad-ram-banks.patch | 1632 +++++++++++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 36 +- test/regfile/sim/tb_ram_2w.cc | 12 +- test/regfile/sim/tb_ram_2w_12.v | 23 + 6 files changed, 1691 insertions(+), 17 deletions(-) create mode 100644 patches/0015-openroad-ram-banks.patch create mode 100644 test/regfile/sim/tb_ram_2w_12.v diff --git a/MODULE.bazel b/MODULE.bazel index ef5a7448f..301fda3ad 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -143,6 +143,10 @@ archive_override( # word, per bit cleared or preset. On 0013 (OpenROAD #11669); not # upstreamed. "//patches:0014-openroad-ram-reset.patch", + # 0015: generate_ram -banks, -bank_columns, -bank_order: words in + # banks, each word decoded whole. On 0014 (OpenROAD #11669); not + # upstreamed. + "//patches:0015-openroad-ram-banks.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0015-openroad-ram-banks.patch b/patches/0015-openroad-ram-banks.patch new file mode 100644 index 000000000..3ca71b0c2 --- /dev/null +++ b/patches/0015-openroad-ram-banks.patch @@ -0,0 +1,1632 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -banks, -bank_columns, -bank_order + +-banks splits the words into banks, contiguous or interleaved in the +address (-bank_order), -bank_columns of them side by side and the rest +stacked, for an array's aspect ratio and for the bank counts register +files use (XiangShan's 224 words in 4 interleaved banks). With banks +every port decodes every word's whole address, an AND2 tree per word, +so a bank need not be a power of two words and any placement of words +reads and writes alike; a row holds -bank_columns words, laid out as the +column mux lays out its words. A read port is one tristate bitline +shared by every word, or one AND-OR tree over all of them. Without +-banks, nothing changes. Not with -column_mux_ratio above 1 or +-use_latch. + +Also: an array with fewer rows than address bits got no address +inverters (ports_per_col was 0), so its decoders read floating +literals; at least one port's inverters now go in each column. + +The fifth of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 7fbfe970a5..8fabb35c70 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -46,6 +46,9 @@ generate_ram [-mask_size bits] + [-read_style tristate|and_or] + [-zero_word word] + [-reset_value value] ++ [-banks count] ++ [-bank_columns count] ++ [-bank_order contiguous|interleaved] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -74,6 +77,7 @@ generate_ram [-mask_size bits] + | `-read_style` | The read path: `tristate`, a tristate bitline per bit, or `and_or`, a tree per bit column of an AOI22 over each pair of rows and NAND2 and NOR2 levels above, for a library without a tristate cell. `and_or` also takes a storage flop whose only output is inverted (QN). Default: `tristate` where the library has a tristate cell, `and_or` where it has none. | + | `-zero_word` | A word that reads 0 and drops its writes, as a RISC-V register file's x0: its row has no flops or clock gate, and the read trees leave it out. Needs `-read_style and_or` and `-column_mux_ratio 1`. Default: none. | + | `-reset_value` | Resets every word to `value` asynchronously, through a reset port at the storage flop's own polarity (`rst_n` or `rst`); each bit's flop is cleared or preset, the other pin held off. The storage cell has both an asynchronous clear and preset. A parent adapts a reset of another polarity, or a synchronous one, to it. Not with `-use_latch`. Default: no reset. | ++| `-banks`, `-bank_columns`, `-bank_order` | The words in `banks` banks, contiguous or interleaved in the address, `bank_columns` of them side by side and the rest stacked. With banks each port decodes every word's whole address, so a bank need not be a power of two words. Not with `-column_mux_ratio` above 1 or `-use_latch`. Default: one bank. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 0f332d5097..c0d47bbf92 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -112,7 +112,10 @@ class RamGen + int max_tap_dist, + const std::string& read_style = "", + int zero_word = -1, +- const std::string& reset_value = ""); ++ const std::string& reset_value = "", ++ int banks = 1, ++ int bank_columns = 1, ++ const std::string& bank_order = "contiguous"); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -158,15 +161,24 @@ class RamGen + odb::dbNet* net; + bool inverted; // the net is the complement of the OR of the terms + }; +- // the tree over rows[lo, hi): rows lists the rows that store a word ++ // one term of a read tree: the word at (row, word in the row) and its ++ // read select ++ struct Term ++ { ++ int row; ++ int word_idx; ++ odb::dbNet* select; ++ }; ++ // the tree over terms[lo, hi), each node in the bit cell of a term it ++ // covers + TreeEnd planReadTree(const std::string& prefix, +- int word_idx, + int bit, +- const std::vector& rows, ++ const std::vector& terms, + int lo, + int hi, +- const std::vector& selects, + odb::dbNet* out); ++ // the word at (row, word in the row) ++ int wordAt(int row, int word_idx) const; + bool treeInverted(int lo, int hi) const; + // -reset_value: the storage flop's data, clear and preset pins, the + // reset's polarity, what a cleared flop reads, and the tie cell that +@@ -246,7 +258,16 @@ class RamGen + void makeBufferColumn(const std::string& prefix, + int num_rows, + const std::vector& decoder_output_nets, +- const std::vector& select_nets); ++ const std::vector& select_nets, ++ int words_per_row = 1); ++ // banks: a decoder per word, an AND2 tree over all its address ++ // literals, the words of a row in that row's cell ++ void makeWordDecoderColumn( ++ const std::string& prefix, ++ int num_rows, ++ int words_per_row, ++ const std::vector>& literals, ++ const std::vector& decoder_output_nets); + + std::unique_ptr makeInverterColumn( + int num_rows, +@@ -322,6 +343,17 @@ class RamGen + std::string read_style_; + bool storage_inverted_{false}; // the storage flop's output is QN + int zero_word_{-1}; // the word that reads 0 and is not stored, or -1 ++ // Banks: the words in `banks_` banks (contiguous or interleaved ++ // addresses), bank_columns_ of them side by side, the rest stacked. ++ // Each port decodes every word's whole address, so any placement of ++ // words reads and writes alike; a row holds bank_columns_ words, its ++ // bits interleaved as the column mux's. ++ bool banked_{false}; ++ int banks_{1}; ++ int bank_columns_{1}; ++ bool bank_interleaved_{false}; ++ int words_per_bank_{0}; ++ int words_per_row_{1}; + // An asynchronous reset to reset_value_ (a word's value, every word): + // each bit's flop is cleared or preset by the reset port, the other + // pin held off. The pins come from the flop's ff group; clear_reads_ +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index a6481b09fd..43a2724490 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -186,54 +186,69 @@ bool RamGen::treeInverted(const int lo, const int hi) const + return !treeInverted(lo, lo + half); + } + ++int RamGen::wordAt(const int row, const int word_idx) const ++{ ++ if (!banked_) { ++ return row * words_per_row_ + word_idx; ++ } ++ const int bank = (row / words_per_bank_) * bank_columns_ + word_idx; ++ const int i = row % words_per_bank_; ++ return bank_interleaved_ ? i * banks_ + bank : bank * words_per_bank_ + i; ++} ++ + RamGen::TreeEnd RamGen::planReadTree(const std::string& prefix, +- const int word_idx, + const int bit, +- const vector& rows, ++ const vector& terms, + const int lo, + const int hi, +- const vector& selects, + dbNet* out) + { +- auto add = [&](const int row, ++ auto add = [&](const Term& at, + dbMaster* master, + const std::string& name, + const vector>& conns) { +- tree_nodes_[{row, word_idx, bit}].push_back({master, prefix, name, conns}); ++ tree_nodes_[{at.row, at.word_idx, bit}].push_back( ++ {master, prefix, name, conns}); + }; + // the zero word's term, where the trees read inverted data: its own + // select, the inverted form of a stored 0 (the zero word is in the + // tree only then) +- auto q = [&](const int row) { +- return row == zero_word_ ? selects[row] +- : storage_nets_.at({row, word_idx, bit}); ++ auto q = [&](const Term& t) { ++ return wordAt(t.row, t.word_idx) == zero_word_ ++ ? t.select ++ : storage_nets_.at({t.row, t.word_idx, bit}); ++ }; ++ // a leaf's name: its row, and with banks its word in the row too ++ auto leaf = [&](const char* kind, const Term& t) { ++ return banked_ ? fmt::format("{}_r{}_w{}", kind, t.row, t.word_idx) ++ : fmt::format("{}_r{}", kind, t.row); + }; + auto net = [&](dbNet* given) { + return given ? given : makeNet(prefix, fmt::format("t{}_{}", lo, hi)); + }; + const int n = hi - lo; + if (n == 1) { +- const int r = rows[lo]; ++ const Term& t = terms[lo]; + dbNet* y = net(out); +- add(r, ++ add(t, + nand2_cell_, +- fmt::format("nand_r{}", r), +- {{nand2_ports_[{PortRoleType::DataIn, 0}], selects[r]}, +- {nand2_ports_[{PortRoleType::DataIn, 1}], q(r)}, ++ leaf("nand", t), ++ {{nand2_ports_[{PortRoleType::DataIn, 0}], t.select}, ++ {nand2_ports_[{PortRoleType::DataIn, 1}], q(t)}, + {nand2_ports_[{PortRoleType::DataOut, 0}], y}}); + return {y, true}; + } + if (n == 2) { +- const int r0 = rows[lo]; +- const int r1 = rows[lo + 1]; ++ const Term& t0 = terms[lo]; ++ const Term& t1 = terms[lo + 1]; + dbNet* y = net(out); +- add(r0, ++ add(t0, + aoi22_cell_, +- fmt::format("aoi_r{}", r0), +- {{aoi22_in_a1_, selects[r0]}, +- {aoi22_in_a2_, q(r0)}, +- {aoi22_in_b1_, selects[r1]}, +- {aoi22_in_b2_, q(r1)}, ++ leaf("aoi", t0), ++ {{aoi22_in_a1_, t0.select}, ++ {aoi22_in_a2_, q(t0)}, ++ {aoi22_in_b1_, t1.select}, ++ {aoi22_in_b2_, q(t1)}, + {aoi22_out_, y}}); + return {y, true}; + } +@@ -242,14 +257,12 @@ RamGen::TreeEnd RamGen::planReadTree(const std::string& prefix, + half *= 2; + } + const int mid = lo + half; +- const int host = rows[mid - 1]; +- const TreeEnd a +- = planReadTree(prefix, word_idx, bit, rows, lo, mid, selects, nullptr); +- TreeEnd b +- = planReadTree(prefix, word_idx, bit, rows, mid, hi, selects, nullptr); ++ const Term& host = terms[mid - 1]; ++ const TreeEnd a = planReadTree(prefix, bit, terms, lo, mid, nullptr); ++ TreeEnd b = planReadTree(prefix, bit, terms, mid, hi, nullptr); + if (b.inverted != a.inverted) { + dbNet* nb = makeNet(prefix, fmt::format("t{}_{}_inv", mid, hi)); +- add(rows[mid], ++ add(terms[mid], + inv_cell_, + fmt::format("inv_r{}_{}", mid, hi), + {{inv_ports_[{PortRoleType::DataIn, 0}], b.net}, +@@ -307,7 +320,7 @@ void RamGen::makeSlice(const int slice_idx, + + // The zero word: no flops, no clock gate; its row's cells hold only + // the read trees' nodes planned there. +- if (row_idx == zero_word_) { ++ if (wordAt(row_idx, word_idx) == zero_word_) { + for (int local_bit = 0; local_bit < mask_size; ++local_bit) { + const int bit = start_bit_idx + local_bit; + std::unique_ptr cell; +@@ -332,7 +345,7 @@ void RamGen::makeSlice(const int slice_idx, + vector select_b_nets(r_total); + if (and_or_read_) { + // the AND-OR trees read the true selects +- } else if (column_mux_ratio == 1) { ++ } else if (column_mux_ratio == 1 || banked_) { + for (int i = 0; i < r_total; ++i) { + select_b_nets[i] = makeNet(prefix, fmt::format("select{}_b", i)); + } +@@ -682,23 +695,80 @@ void RamGen::makeDecoderColumn( + void RamGen::makeBufferColumn(const std::string& prefix, + const int num_rows, + const std::vector& decoder_output_nets, +- const std::vector& select_nets) ++ const std::vector& select_nets, ++ const int words_per_row) + { + auto buffer_layout = std::make_unique(odb::vertical); +- for (int word = 0; word < num_rows; ++word) { ++ for (int row = 0; row < num_rows; ++row) { + auto buf_cell = std::make_unique(); +- makeInst( +- buf_cell.get(), +- prefix, +- fmt::format("sel_buf_{}", word), +- buffer_cell_, +- {{buffer_ports_[{PortRoleType::DataIn, 0}], decoder_output_nets[word]}, +- {buffer_ports_[{PortRoleType::DataOut, 0}], select_nets[word]}}); ++ // a buffer per select: one per row, or with banks one per word ++ for (int k = 0; k < words_per_row; ++k) { ++ const int word = row * words_per_row + k; ++ makeInst( ++ buf_cell.get(), ++ prefix, ++ fmt::format("sel_buf_{}", word), ++ buffer_cell_, ++ {{buffer_ports_[{PortRoleType::DataIn, 0}], decoder_output_nets[word]}, ++ {buffer_ports_[{PortRoleType::DataOut, 0}], select_nets[word]}}); ++ } + buffer_layout->addCell(std::move(buf_cell)); + } + ram_grid_.addLayout(std::move(buffer_layout)); + } + ++void RamGen::makeWordDecoderColumn( ++ const std::string& prefix, ++ const int num_rows, ++ const int words_per_row, ++ const std::vector>& literals, ++ const std::vector& decoder_output_nets) ++{ ++ auto decoder_layout = std::make_unique(odb::vertical); ++ for (int row = 0; row < num_rows; ++row) { ++ auto row_cell = std::make_unique(); ++ for (int k = 0; k < words_per_row; ++k) { ++ const int word = row * words_per_row + k; ++ // a balanced AND2 tree over the word's address literals ++ vector level = literals[word]; ++ int node = 0; ++ while (level.size() > 1) { ++ vector next; ++ for (size_t i = 0; i + 1 < level.size(); i += 2) { ++ dbNet* y = level.size() == 2 ++ ? decoder_output_nets[word] ++ : makeNet(prefix, ++ fmt::format("y{}_word{}", node, word)); ++ makeInst(row_cell.get(), ++ prefix, ++ fmt::format("and{}_word{}", node++, word), ++ and2_cell_, ++ {{and2_ports_[{PortRoleType::DataIn, 0}], level[i]}, ++ {and2_ports_[{PortRoleType::DataIn, 1}], level[i + 1]}, ++ {and2_ports_[{PortRoleType::DataOut, 0}], y}}); ++ next.push_back(y); ++ } ++ if (level.size() % 2 == 1) { ++ next.push_back(level.back()); ++ } ++ level = std::move(next); ++ } ++ if (literals[word].size() == 1) { ++ // a single literal: buffered to the decoder's output ++ makeInst(row_cell.get(), ++ prefix, ++ fmt::format("buf_word{}", word), ++ buffer_cell_, ++ {{buffer_ports_[{PortRoleType::DataIn, 0}], level[0]}, ++ {buffer_ports_[{PortRoleType::DataOut, 0}], ++ decoder_output_nets[word]}}); ++ } ++ } ++ decoder_layout->addCell(std::move(row_cell)); ++ } ++ ram_grid_.addLayout(std::move(decoder_layout)); ++} ++ + std::unique_ptr RamGen::makeInverterColumn( + const int num_rows, + const int num_row_bits, +@@ -1669,7 +1739,7 @@ void RamGen::generate(const int mask_size, + const int rw_ports, + const int r_ports, + const int w_ports, +- const int column_mux_ratio, ++ const int column_mux_ratio_arg, + const bool use_latch, + dbMaster* storage_cell, + dbMaster* tristate_cell, +@@ -1678,8 +1748,40 @@ void RamGen::generate(const int mask_size, + int max_tap_dist, + const std::string& read_style, + const int zero_word, +- const std::string& reset_value) ++ const std::string& reset_value, ++ const int banks, ++ const int bank_columns, ++ const std::string& bank_order) + { ++ // Banks: every port decodes every word's whole address, and a row holds ++ // bank_columns words, laid out as the column mux lays out its words; ++ // without banks, the column mux as it was. ++ banked_ = banks > 1 || bank_columns > 1; ++ banks_ = std::max(banks, 1); ++ bank_columns_ = std::max(bank_columns, 1); ++ bank_interleaved_ = bank_order == "interleaved"; ++ if (banked_) { ++ if (column_mux_ratio_arg != 1) { ++ logger_->error( ++ RAM, 66, "-banks is not supported with -column_mux_ratio above 1."); ++ } ++ if (num_words % banks_ != 0 || banks_ % bank_columns_ != 0) { ++ logger_->error(RAM, ++ 67, ++ "-num_words {} must divide into -banks {}, and the banks " ++ "into -bank_columns {}.", ++ num_words, ++ banks_, ++ bank_columns_); ++ } ++ if (use_latch) { ++ logger_->error(RAM, 68, "-banks is not supported with -use_latch."); ++ } ++ } ++ words_per_bank_ = num_words / banks_; ++ // the words in a row: the column mux's, or the banks side by side ++ const int column_mux_ratio = banked_ ? bank_columns_ : column_mux_ratio_arg; ++ words_per_row_ = column_mux_ratio; + if (num_words / column_mux_ratio == 1) { + logger_->error(RAM, 42, "1-row RAMs are not supported."); + } +@@ -1687,7 +1789,8 @@ void RamGen::generate(const int mask_size, + const std::string ram_name = fmt::format("RAM{}x{}", num_words, word_size); + + // error checking for column_mux_ratio +- if (column_mux_ratio != 1 && column_mux_ratio != 2 && column_mux_ratio != 4) { ++ if (!banked_ && column_mux_ratio != 1 && column_mux_ratio != 2 ++ && column_mux_ratio != 4) { + logger_->error(RAM, + 33, + "The ram generator currently only supports column_mux_ratio " +@@ -1715,7 +1818,8 @@ void RamGen::generate(const int mask_size, + const int num_rows = num_words / column_mux_ratio; + // if column mux ratio > 1, then the lower log2(column_mux_ratio) bits are + // used to select the word within a row +- const int num_word_bits = (column_mux_ratio > 1) ++ // (with banks, none: each port decodes every word's whole address) ++ const int num_word_bits = (column_mux_ratio > 1 && !banked_) + ? static_cast(std::log2(column_mux_ratio)) + : 0; + // the remaining upper bits are used to select the row +@@ -1784,7 +1888,7 @@ void RamGen::generate(const int mask_size, + zero_word_, + num_words); + } +- if (!and_or_read_ || column_mux_ratio != 1) { ++ if (!and_or_read_ || (column_mux_ratio != 1 && !banked_)) { + logger_->error(RAM, + 60, + "-zero_word needs -read_style and_or and " +@@ -1807,8 +1911,10 @@ void RamGen::generate(const int mask_size, + // Each read/write port gets a buffer col and decoder col, + // plus inverter columns shared across ports + const int total_ports = rw_ports + r_ports + w_ports; ++ // at least one port's inverters a column: an array with fewer rows than ++ // address bits (four banks side by side, say) otherwise got none + const int ports_per_col +- = (num_row_bits > 0) ? (num_rows / num_row_bits) : total_ports; ++ = (num_row_bits > 0) ? std::max(1, num_rows / num_row_bits) : total_ports; + const int inv_col_count + = std::ceil(static_cast(total_ports) / ports_per_col); + +@@ -1900,9 +2006,26 @@ void RamGen::generate(const int mask_size, + = makeNet(port_prefix, fmt::format("inv_addr[{}]", i)); + } + +- // inputs to decoders ++ // inputs to decoders: with banks, every word's whole address, one ++ // decoder per word (slot row * words per row + word in the row) ++ if (banked_) { ++ decoder_input_nets[p].assign(num_rows * column_mux_ratio, ++ vector(num_inputs)); ++ for (int row = 0; row < num_rows; ++row) { ++ for (int w = 0; w < column_mux_ratio; ++w) { ++ const int word = wordAt(row, w); ++ for (int input = 0; input < num_inputs; ++input) { ++ decoder_input_nets[p][row * column_mux_ratio + w][input] ++ = ((word >> input) & 1) ? addr_inputs_[p][input]->getNet() ++ : inv_addr_nets[p][input]; ++ } ++ } ++ } ++ } ++ if (!banked_) { + decoder_input_nets[p].assign(num_rows, vector(num_row_bits)); +- for (int row = 0; row < num_rows; ++row) { ++ } ++ for (int row = 0; row < num_rows && !banked_; ++row) { + int row_num = row; + // start at right most bit + for (int input = 0; input < num_row_bits; ++input) { +@@ -1919,23 +2042,24 @@ void RamGen::generate(const int mask_size, + } + + // output nets of each port decoder ++ const int num_selects = banked_ ? num_rows * column_mux_ratio : num_rows; + decoder_output_nets[p] +- = makeDecoderOutputNets(fmt::format("decoder_p{}", p), num_rows); ++ = makeDecoderOutputNets(fmt::format("decoder_p{}", p), num_selects); + // output nets of each decoder buffers + // write-capable ports to index 0 since there can only be 1 + if (p < rw_ports) { + write_select_nets[w_sel_idx] = makeSelectNets( +- fmt::format("rw_sel_p{}", p), num_rows, RamPortType::ReadWrite); ++ fmt::format("rw_sel_p{}", p), num_selects, RamPortType::ReadWrite); + read_select_nets[r_sel_idx++] = write_select_nets[w_sel_idx]; + ++w_sel_idx; + } else if (p < rw_ports + w_ports) { + write_select_nets[w_sel_idx] = makeSelectNets( +- fmt::format("w_sel_p{}", p), num_rows, RamPortType::Write); ++ fmt::format("w_sel_p{}", p), num_selects, RamPortType::Write); + ++w_sel_idx; + } + if (p >= rw_ports + w_ports) { + read_select_nets[r_sel_idx++] = makeSelectNets( +- fmt::format("r_sel_p{}", p), num_rows, RamPortType::Read); ++ fmt::format("r_sel_p{}", p), num_selects, RamPortType::Read); + } + } + +@@ -1975,10 +2099,14 @@ void RamGen::generate(const int mask_size, + vector>> word_q_nets( + column_mux_ratio, + vector>(r_total, vector(word_size))); +- if (column_mux_ratio == 1) { +- for (int port = 0; port < r_total; ++port) { +- for (int bit = 0; bit < word_size; ++bit) { +- word_q_nets[0][port][bit] = q_outputs_[port][bit]->getNet(); ++ // with banks every word drives the read port's own net: a tristate ++ // bitline shared by every word, or one AND-OR tree over all of them ++ if (column_mux_ratio == 1 || banked_) { ++ for (int w = 0; w < column_mux_ratio; ++w) { ++ for (int port = 0; port < r_total; ++port) { ++ for (int bit = 0; bit < word_size; ++bit) { ++ word_q_nets[w][port][bit] = q_outputs_[port][bit]->getNet(); ++ } + } + } + +@@ -1994,10 +2122,10 @@ void RamGen::generate(const int mask_size, + } + + // Word selects for column mux, placed before word creation +- if (column_mux_ratio == 2) { ++ if (column_mux_ratio == 2 && !banked_) { + word_sel_nets[0] = inv_addr_nets[0][0]; + word_sel_nets[1] = addr_inputs_[0][0]->getNet(); +- } else if (column_mux_ratio == 4) { ++ } else if (column_mux_ratio == 4 && !banked_) { + for (int c = 0; c < 4; ++c) { + word_sel_nets[c] = makeNet("word_sel", fmt::format("{}", c)); + } +@@ -2019,25 +2147,27 @@ void RamGen::generate(const int mask_size, + // gate — all other word_idx reuse the existing net, reducing cell count + // and horizontal routing congestion in storage rows. + ++ // a port's select of the word at (row, word in the row): with banks a ++ // select per word, else per row ++ auto select_at ++ = [&](const vector& selects, const int row, const int w) { ++ return banked_ ? selects[row * column_mux_ratio + w] : selects[row]; ++ }; ++ + // The AND-OR read path: every storage net named ahead, and every + // bitline's tree planned, so each row's bit cells take their nodes. + // Where the storage flop's output is QN, or the tree's root is + // inverted, but not both, an inverter at the bottom row puts it right. + if (and_or_read_) { +- // The rows in the trees: where the storage output is inverted the +- // final inverter assumes some row's term is the read's, so the zero ++ // The words in the trees: where the storage output is inverted the ++ // final inverter assumes some word's term is the read's, so the zero + // word stays, its term a 1; otherwise its term would be a 0, and it + // is left out. +- vector stored_rows; + for (int row = 0; row < num_rows; ++row) { +- if (row == zero_word_) { +- if (storage_inverted_) { +- stored_rows.push_back(row); +- } +- continue; +- } +- stored_rows.push_back(row); + for (int w = 0; w < column_mux_ratio; ++w) { ++ if (wordAt(row, w) == zero_word_) { ++ continue; ++ } + for (int bit = 0; bit < word_size; ++bit) { + const std::string prefix = fmt::format( + "storage_{}_{}_{}", row, w, (bit / mask_size) * mask_size); +@@ -2046,25 +2176,38 @@ void RamGen::generate(const int mask_size, + } + } + } +- const int stored = static_cast(stored_rows.size()); +- const bool flip = treeInverted(0, stored) != storage_inverted_; +- for (int w = 0; w < column_mux_ratio; ++w) { ++ // a read port's terms: with banks every word, a column at a time; else ++ // the words of column w ++ auto terms_of = [&](const int port, const int only_w) { ++ vector terms; ++ for (int w = 0; w < column_mux_ratio; ++w) { ++ if (!banked_ && w != only_w) { ++ continue; ++ } ++ for (int row = 0; row < num_rows; ++row) { ++ if (wordAt(row, w) == zero_word_ && !storage_inverted_) { ++ continue; ++ } ++ terms.push_back({row, w, select_at(read_select_nets[port], row, w)}); ++ } ++ } ++ return terms; ++ }; ++ for (int w = 0; w < (banked_ ? 1 : column_mux_ratio); ++w) { + for (int port = 0; port < r_total; ++port) { ++ const vector terms = terms_of(port, w); ++ const int n = static_cast(terms.size()); ++ const bool flip = treeInverted(0, n) != storage_inverted_; + for (int bit = 0; bit < word_size; ++bit) { + const std::string prefix +- = fmt::format("read_w{}_p{}_b{}", w, port, bit); ++ = banked_ ? fmt::format("read_p{}_b{}", port, bit) ++ : fmt::format("read_w{}_p{}_b{}", w, port, bit); + dbNet* out = word_q_nets[w][port][bit]; + const TreeEnd root +- = planReadTree(prefix, +- w, +- bit, +- stored_rows, +- 0, +- stored, +- read_select_nets[port], +- flip ? nullptr : out); ++ = planReadTree(prefix, bit, terms, 0, n, flip ? nullptr : out); + if (flip) { +- tree_nodes_[{num_rows - 1, w, bit}].push_back( ++ const Term& at = banked_ ? terms.back() : Term{num_rows - 1, w, nullptr}; ++ tree_nodes_[{at.row, at.word_idx, bit}].push_back( + {inv_cell_, + prefix, + "out_inv", +@@ -2079,7 +2222,7 @@ void RamGen::generate(const int mask_size, + for (int row = 0; row < num_rows; ++row) { + // one select_b_net per row for column_mux_ratio > 1 + vector shared_select_b_nets(r_total); +- if (column_mux_ratio > 1) { ++ if (column_mux_ratio > 1 && !banked_) { + for (int i = 0; i < r_total; ++i) { + shared_select_b_nets[i] + = makeNet(fmt::format("row{}", row), fmt::format("select{}_b", i)); +@@ -2090,10 +2233,11 @@ void RamGen::generate(const int mask_size, + // the write ports' row selects, then the read ports' + vector row_selects(num_write + r_total); + for (int p = 0; p < num_write; ++p) { +- row_selects[p] = write_select_nets[p][row]; ++ row_selects[p] = select_at(write_select_nets[p], row, word_idx); + } + for (int p = 0; p < r_total; ++p) { +- row_selects[num_write + p] = read_select_nets[p][row]; ++ row_selects[num_write + p] ++ = select_at(read_select_nets[p], row, word_idx); + } + vector> word_output_nets(r_total); + for (int port = 0; port < r_total; ++port) { +@@ -2115,15 +2259,15 @@ void RamGen::generate(const int mask_size, + write_enable, + row_selects, + shared_select_b_nets, +- (word_idx == 0 || column_mux_ratio == 1), ++ (word_idx == 0 || column_mux_ratio == 1 || banked_), + use_latch_ ? vector>{mid_nets} : D_nets, + word_output_nets); + } + } + + // cell placement for mux made of AOI22 (and inverter if needed) for column +- // muxing +- if (column_mux_ratio > 1) { ++ // muxing (with banks each port's tree or bitline spans every word) ++ if (column_mux_ratio > 1 && !banked_) { + for (int slice = 0; slice < slices_per_word; ++slice) { + for (int bit = 0; bit < mask_size; ++bit) { + const int global_bit = slice * mask_size + bit; +@@ -2311,26 +2455,37 @@ void RamGen::generate(const int mask_size, + makeBufferColumn(fmt::format("sel_buf_rw_p{}", p), + num_rows, + decoder_output_nets[p], +- write_select_nets[w_buf_idx++]); ++ write_select_nets[w_buf_idx++], ++ banked_ ? column_mux_ratio : 1); + ++r_buf_idx; // so that next read port doesn't use the rw_select + } else if (p < rw_ports + w_ports) { + makeBufferColumn(fmt::format("sel_buf_w_p{}", p), + num_rows, + decoder_output_nets[p], +- write_select_nets[w_buf_idx++]); ++ write_select_nets[w_buf_idx++], ++ banked_ ? column_mux_ratio : 1); + } + if (p >= rw_ports + w_ports) { + makeBufferColumn(fmt::format("sel_buf_r_p{}", p), + num_rows, + decoder_output_nets[p], +- read_select_nets[r_buf_idx++]); ++ read_select_nets[r_buf_idx++], ++ banked_ ? column_mux_ratio : 1); + } + + // decoder column creation +- makeDecoderColumn(fmt::format("decoder_p{}", p), +- num_rows, +- decoder_input_nets[p], +- decoder_output_nets[p]); ++ if (banked_) { ++ makeWordDecoderColumn(fmt::format("decoder_p{}", p), ++ num_rows, ++ column_mux_ratio, ++ decoder_input_nets[p], ++ decoder_output_nets[p]); ++ } else { ++ makeDecoderColumn(fmt::format("decoder_p{}", p), ++ num_rows, ++ decoder_input_nets[p], ++ decoder_output_nets[p]); ++ } + } + + if (num_row_bits > 0) { +@@ -2350,7 +2505,7 @@ void RamGen::generate(const int mask_size, + std::unique_ptr inv_sel_cell = std::make_unique(); + std::vector> word_sel_cells(column_mux_ratio); + +- if (column_mux_ratio == 2) { ++ if (column_mux_ratio == 2 && !banked_) { + // place inv_addr[0] inverter in sel column + makeInst( + inv_sel_cell.get(), +@@ -2359,7 +2514,7 @@ void RamGen::generate(const int mask_size, + inv_cell_, + {{inv_ports_[{PortRoleType::DataIn, 0}], addr_inputs_[0][0]->getNet()}, + {inv_ports_[{PortRoleType::DataOut, 0}], inv_addr_nets[0][0]}}); +- } else if (column_mux_ratio == 4) { ++ } else if (column_mux_ratio == 4 && !banked_) { + for (int c = 0; c < 4; ++c) { + word_sel_cells[c] = std::make_unique(); + } +@@ -2413,9 +2568,9 @@ void RamGen::generate(const int mask_size, + + // moving column_mux select cells to the top row to be closer to connected + // nets also removes extra column that sits to the right of decoders +- if (column_mux_ratio == 2) { ++ if (column_mux_ratio == 2 && !banked_) { + ram_grid_.addCell(std::move(inv_sel_cell), mask_size * column_mux_ratio); +- } else if (column_mux_ratio == 4) { ++ } else if (column_mux_ratio == 4 && !banked_) { + for (int c = 0; c < 4; ++c) { + int sel_col = mask_size * column_mux_ratio + c; + ram_grid_.addCell(std::move(word_sel_cells[c]), sel_col); +@@ -2423,7 +2578,7 @@ void RamGen::generate(const int mask_size, + } + + // adding filler cells to ease congestion for multi-port +- if (column_mux_ratio > 1 && total_ports > 1) { ++ if (column_mux_ratio > 1 && total_ports > 1 && !banked_) { + int filler_spacing = num_rows / (column_mux_ratio - 1); + if (filler_spacing > 0) { + int filler_count = 0; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 9ccfcf5790..d5eb7723c5 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -45,7 +45,10 @@ generate_ram_netlist_cmd(int mask_size, + const int max_tap_dist, + const char* read_style, + const int zero_word, +- const char* reset_value) ++ const char* reset_value, ++ const int banks, ++ const int bank_columns, ++ const char* bank_order) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -98,7 +101,7 @@ generate_ram_netlist_cmd(int mask_size, + ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, +- reset_value); ++ reset_value, banks, bank_columns, bank_order); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 6d41e0bda8..315a3d88bd 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -10,8 +10,14 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-read_style tristate|and_or] + [-zero_word word] + [-reset_value value] ++ [-banks count] ++ [-bank_columns count] ++ [-bank_order contiguous|interleaved] + [-zero_word word] + [-reset_value value] ++ [-banks count] ++ [-bank_columns count] ++ [-bank_order contiguous|interleaved] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -24,7 +30,8 @@ proc generate_ram_netlist { args } { + sta::parse_key_args "generate_ram_netlist" args \ + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist +- -write_behavioral_verilog -read_style -zero_word -reset_value } flags {} ++ -write_behavioral_verilog -read_style -zero_word -reset_value ++ -banks -bank_columns -bank_order } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -160,9 +167,27 @@ proc generate_ram_netlist { args } { + set reset_value $keys(-reset_value) + } + ++ # Banks: the words in banks, contiguous or interleaved addresses, ++ # bank_columns of them side by side and the rest stacked. ++ set banks 1 ++ if { [info exists keys(-banks)] } { ++ set banks $keys(-banks) ++ } ++ set bank_columns 1 ++ if { [info exists keys(-bank_columns)] } { ++ set bank_columns $keys(-bank_columns) ++ } ++ set bank_order contiguous ++ if { [info exists keys(-bank_order)] } { ++ set bank_order $keys(-bank_order) ++ if { $bank_order ni {contiguous interleaved} } { ++ utl::error RAM 69 "-bank_order is contiguous or interleaved, not $bank_order." ++ } ++ } ++ + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ +- $read_style $zero_word $reset_value ++ $read_style $zero_word $reset_value $banks $bank_columns $bank_order + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -196,7 +221,8 @@ proc generate_ram { args } { + -r_ports -w_ports -use_latch -power_net_name + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist +- -write_behavioral_verilog -read_style -zero_word -reset_value } flags {} ++ -write_behavioral_verilog -read_style -zero_word -reset_value ++ -banks -bank_columns -bank_order } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -245,6 +271,12 @@ proc generate_ram { args } { + lappend ram_netlist_args -reset_value $keys(-reset_value) + } + ++ foreach key {-banks -bank_columns -bank_order} { ++ if { [info exists keys($key)] } { ++ lappend ram_netlist_args $key $keys($key) ++ } ++ } ++ + if { [info exists keys(-inv_cell)] } { + lappend ram_netlist_args -inv_cell $keys(-inv_cell) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index b964c56b3b..fdb75124a0 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_2r1w_banks_asap7", + "make_8x8_2r1w_reset_asap7", + "make_8x8_2r1w_zero_asap7", + "make_8x8_2r1w_and_or_asap7", +@@ -104,6 +105,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_reset_asap7_behavioral.vok", + ], ++ "make_8x8_2r1w_banks_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_banks_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_banks_asap7.defok b/src/ram/test/make_8x8_2r1w_banks_asap7.defok +new file mode 100644 +index 0000000000..d256650695 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_banks_asap7.defok +@@ -0,0 +1,649 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 3591 135 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 665 BY 1 STEP 5 0 ; ++COMPONENTS 271 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 1382 108 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1728 108 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 2073 108 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 2419 108 ) N ; ++ - decoder_p0.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3067 0 ) N ; ++ - decoder_p0.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3132 0 ) N ; ++ - decoder_p0.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3067 27 ) FS ; ++ - decoder_p0.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3132 27 ) FS ; ++ - decoder_p0.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3067 54 ) N ; ++ - decoder_p0.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3132 54 ) N ; ++ - decoder_p0.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3067 81 ) FS ; ++ - decoder_p0.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3132 81 ) FS ; ++ - decoder_p0.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3099 0 ) N ; ++ - decoder_p0.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3164 0 ) N ; ++ - decoder_p0.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3099 27 ) FS ; ++ - decoder_p0.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3164 27 ) FS ; ++ - decoder_p0.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3099 54 ) N ; ++ - decoder_p0.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3164 54 ) N ; ++ - decoder_p0.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3099 81 ) FS ; ++ - decoder_p0.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3164 81 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 3542 54 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 3542 27 ) FS ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 3542 0 ) N ; ++ - decoder_p1.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3240 0 ) N ; ++ - decoder_p1.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3304 0 ) N ; ++ - decoder_p1.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3240 27 ) FS ; ++ - decoder_p1.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3304 27 ) FS ; ++ - decoder_p1.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3240 54 ) N ; ++ - decoder_p1.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3304 54 ) N ; ++ - decoder_p1.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3240 81 ) FS ; ++ - decoder_p1.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3304 81 ) FS ; ++ - decoder_p1.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3272 0 ) N ; ++ - decoder_p1.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3337 0 ) N ; ++ - decoder_p1.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3272 27 ) FS ; ++ - decoder_p1.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3337 27 ) FS ; ++ - decoder_p1.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3272 54 ) N ; ++ - decoder_p1.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3337 54 ) N ; ++ - decoder_p1.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3272 81 ) FS ; ++ - decoder_p1.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3337 81 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 3558 54 ) N ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 3558 27 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 3558 0 ) N ; ++ - decoder_p2.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3412 0 ) N ; ++ - decoder_p2.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3477 0 ) N ; ++ - decoder_p2.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3412 27 ) FS ; ++ - decoder_p2.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3477 27 ) FS ; ++ - decoder_p2.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3412 54 ) N ; ++ - decoder_p2.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3477 54 ) N ; ++ - decoder_p2.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3412 81 ) FS ; ++ - decoder_p2.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3477 81 ) FS ; ++ - decoder_p2.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3445 0 ) N ; ++ - decoder_p2.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3510 0 ) N ; ++ - decoder_p2.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3445 27 ) FS ; ++ - decoder_p2.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3510 27 ) FS ; ++ - decoder_p2.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3445 54 ) N ; ++ - decoder_p2.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3510 54 ) N ; ++ - decoder_p2.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3445 81 ) FS ; ++ - decoder_p2.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3510 81 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 3574 54 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 3574 27 ) FS ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 3574 0 ) N ; ++ - read_p0_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - read_p0_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 280 0 ) N ; ++ - read_p0_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_p0_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_p0_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - read_p0_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 626 0 ) N ; ++ - read_p0_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_p0_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_p0_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - read_p0_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 972 0 ) N ; ++ - read_p0_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_p0_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_p0_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - read_p0_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 0 ) N ; ++ - read_p0_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_p0_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_p0_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1382 0 ) N ; ++ - read_p0_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1663 0 ) N ; ++ - read_p0_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1490 54 ) N ; ++ - read_p0_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1663 54 ) N ; ++ - read_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1490 27 ) FS ; ++ - read_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1663 27 ) FS ; ++ - read_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1490 81 ) FS ; ++ - read_p0_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1728 0 ) N ; ++ - read_p0_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2008 0 ) N ; ++ - read_p0_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 54 ) N ; ++ - read_p0_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2008 54 ) N ; ++ - read_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1836 27 ) FS ; ++ - read_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2008 27 ) FS ; ++ - read_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1836 81 ) FS ; ++ - read_p0_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2073 0 ) N ; ++ - read_p0_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2354 0 ) N ; ++ - read_p0_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2181 54 ) N ; ++ - read_p0_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2354 54 ) N ; ++ - read_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2181 27 ) FS ; ++ - read_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2354 27 ) FS ; ++ - read_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2181 81 ) FS ; ++ - read_p0_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2419 0 ) N ; ++ - read_p0_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2700 0 ) N ; ++ - read_p0_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2527 54 ) N ; ++ - read_p0_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2700 54 ) N ; ++ - read_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2527 27 ) FS ; ++ - read_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2700 27 ) FS ; ++ - read_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2527 81 ) FS ; ++ - read_p1_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 32 0 ) N ; ++ - read_p1_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 313 0 ) N ; ++ - read_p1_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_p1_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 129 27 ) FS ; ++ - read_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 302 27 ) FS ; ++ - read_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 129 81 ) FS ; ++ - read_p1_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 378 0 ) N ; ++ - read_p1_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 658 0 ) N ; ++ - read_p1_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_p1_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - read_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - read_p1_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 723 0 ) N ; ++ - read_p1_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 0 ) N ; ++ - read_p1_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_p1_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - read_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 993 27 ) FS ; ++ - read_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - read_p1_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1069 0 ) N ; ++ - read_p1_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 0 ) N ; ++ - read_p1_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_p1_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 27 ) FS ; ++ - read_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 27 ) FS ; ++ - read_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1166 81 ) FS ; ++ - read_p1_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1414 0 ) N ; ++ - read_p1_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1695 0 ) N ; ++ - read_p1_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1522 54 ) N ; ++ - read_p1_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1695 54 ) N ; ++ - read_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1512 27 ) FS ; ++ - read_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1684 27 ) FS ; ++ - read_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1512 81 ) FS ; ++ - read_p1_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1760 0 ) N ; ++ - read_p1_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2041 0 ) N ; ++ - read_p1_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 54 ) N ; ++ - read_p1_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2041 54 ) N ; ++ - read_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1857 27 ) FS ; ++ - read_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2030 27 ) FS ; ++ - read_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1857 81 ) FS ; ++ - read_p1_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2106 0 ) N ; ++ - read_p1_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2386 0 ) N ; ++ - read_p1_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2214 54 ) N ; ++ - read_p1_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2386 54 ) N ; ++ - read_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2203 27 ) FS ; ++ - read_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2376 27 ) FS ; ++ - read_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2203 81 ) FS ; ++ - read_p1_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2451 0 ) N ; ++ - read_p1_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2732 0 ) N ; ++ - read_p1_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2559 54 ) N ; ++ - read_p1_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2732 54 ) N ; ++ - read_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2548 27 ) FS ; ++ - read_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2721 27 ) FS ; ++ - read_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2548 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3196 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3218 0 ) N ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3196 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3218 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3196 54 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3218 54 ) N ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3196 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3218 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3369 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3391 0 ) N ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3369 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3391 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3369 54 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3391 54 ) N ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3369 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3391 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3024 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3045 0 ) N ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3024 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3045 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3024 54 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3045 54 ) N ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3024 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3045 81 ) FS ; ++ - storage_0_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - storage_0_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - storage_0_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - storage_0_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - storage_0_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 0 ) N ; ++ - storage_0_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 0 ) N ; ++ - storage_0_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 0 ) N ; ++ - storage_0_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 0 ) N ; ++ - storage_0_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 0 ) N ; ++ - storage_0_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 27 ) FS ; ++ - storage_1_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 27 ) FS ; ++ - storage_1_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 27 ) FS ; ++ - storage_1_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 27 ) FS ; ++ - storage_1_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 27 ) FS ; ++ - storage_1_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 27 ) FS ; ++ - storage_1_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 54 ) N ; ++ - storage_2_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 54 ) N ; ++ - storage_2_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 54 ) N ; ++ - storage_2_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 54 ) N ; ++ - storage_2_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 54 ) N ; ++ - storage_2_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 54 ) N ; ++ - storage_2_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 81 ) FS ; ++ - storage_3_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 81 ) FS ; ++ - storage_3_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 81 ) FS ; ++ - storage_3_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 81 ) FS ; ++ - storage_3_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 81 ) FS ; ++ - storage_3_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 81 ) FS ; ++ - storage_3_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 81 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 290 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_3_1_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_1_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ( storage_1_1_0.bit0.bit D ) ( storage_1_0_0.bit0.bit D ) ++ ( storage_0_1_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_3_1_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_1_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ( storage_1_1_0.bit1.bit D ) ( storage_1_0_0.bit1.bit D ) ++ ( storage_0_1_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_3_1_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_1_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ( storage_1_1_0.bit2.bit D ) ( storage_1_0_0.bit2.bit D ) ++ ( storage_0_1_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_3_1_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_1_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ( storage_1_1_0.bit3.bit D ) ( storage_1_0_0.bit3.bit D ) ++ ( storage_0_1_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_3_1_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_1_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ( storage_1_1_0.bit4.bit D ) ( storage_1_0_0.bit4.bit D ) ++ ( storage_0_1_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_3_1_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_1_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ( storage_1_1_0.bit5.bit D ) ( storage_1_0_0.bit5.bit D ) ++ ( storage_0_1_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_3_1_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_1_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ( storage_1_1_0.bit6.bit D ) ( storage_1_0_0.bit6.bit D ) ++ ( storage_0_1_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_3_1_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_1_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ( storage_1_1_0.bit7.bit D ) ( storage_1_0_0.bit7.bit D ) ++ ( storage_0_1_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and0_word6 A ) ( decoder_p1.and0_word4 A ) ( decoder_p1.and0_word2 A ) ( decoder_p1.and0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and0_word3 B ) ( decoder_p1.and0_word2 B ) ( decoder_p1.and0_word1 B ) ( decoder_p1.and0_word0 B ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and1_word5 B ) ( decoder_p1.and1_word4 B ) ( decoder_p1.and1_word1 B ) ( decoder_p1.and1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and0_word7 A ) ( decoder_p1.and0_word5 A ) ( decoder_p1.and0_word3 A ) ( decoder_p1.and0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and0_word7 B ) ( decoder_p1.and0_word6 B ) ( decoder_p1.and0_word5 B ) ( decoder_p1.and0_word4 B ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and1_word7 B ) ( decoder_p1.and1_word6 B ) ( decoder_p1.and1_word3 B ) ( decoder_p1.and1_word2 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and0_word6 A ) ( decoder_p2.and0_word4 A ) ( decoder_p2.and0_word2 A ) ( decoder_p2.and0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and0_word3 B ) ( decoder_p2.and0_word2 B ) ( decoder_p2.and0_word1 B ) ( decoder_p2.and0_word0 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and1_word5 B ) ( decoder_p2.and1_word4 B ) ( decoder_p2.and1_word1 B ) ( decoder_p2.and1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and0_word7 A ) ( decoder_p2.and0_word5 A ) ( decoder_p2.and0_word3 A ) ( decoder_p2.and0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and0_word7 B ) ( decoder_p2.and0_word6 B ) ( decoder_p2.and0_word5 B ) ( decoder_p2.and0_word4 B ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and1_word7 B ) ( decoder_p2.and1_word6 B ) ( decoder_p2.and1_word3 B ) ( decoder_p2.and1_word2 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and0_word6 A ) ( decoder_p0.and0_word4 A ) ( decoder_p0.and0_word2 A ) ( decoder_p0.and0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and0_word3 B ) ( decoder_p0.and0_word2 B ) ( decoder_p0.and0_word1 B ) ( decoder_p0.and0_word0 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and1_word5 B ) ( decoder_p0.and1_word4 B ) ( decoder_p0.and1_word1 B ) ( decoder_p0.and1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and0_word7 A ) ( decoder_p0.and0_word5 A ) ( decoder_p0.and0_word3 A ) ( decoder_p0.and0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and0_word7 B ) ( decoder_p0.and0_word6 B ) ( decoder_p0.and0_word5 B ) ( decoder_p0.and0_word4 B ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and1_word7 B ) ( decoder_p0.and1_word6 B ) ( decoder_p0.and1_word3 B ) ( decoder_p0.and1_word2 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_3_1_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_1_0.cg CLK ) ( storage_2_0_0.cg CLK ) ( storage_1_1_0.cg CLK ) ( storage_1_0_0.cg CLK ) ++ ( storage_0_1_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and1_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and1_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and1_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and1_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and1_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and1_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and1_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and1_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p0.y0_word0 ( decoder_p0.and1_word0 A ) ( decoder_p0.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word1 ( decoder_p0.and1_word1 A ) ( decoder_p0.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word2 ( decoder_p0.and1_word2 A ) ( decoder_p0.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word3 ( decoder_p0.and1_word3 A ) ( decoder_p0.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word4 ( decoder_p0.and1_word4 A ) ( decoder_p0.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word5 ( decoder_p0.and1_word5 A ) ( decoder_p0.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word6 ( decoder_p0.and1_word6 A ) ( decoder_p0.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word7 ( decoder_p0.and1_word7 A ) ( decoder_p0.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and1_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and1_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and1_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and1_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and1_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and1_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and1_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and1_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.y0_word0 ( decoder_p1.and1_word0 A ) ( decoder_p1.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word1 ( decoder_p1.and1_word1 A ) ( decoder_p1.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word2 ( decoder_p1.and1_word2 A ) ( decoder_p1.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word3 ( decoder_p1.and1_word3 A ) ( decoder_p1.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word4 ( decoder_p1.and1_word4 A ) ( decoder_p1.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word5 ( decoder_p1.and1_word5 A ) ( decoder_p1.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word6 ( decoder_p1.and1_word6 A ) ( decoder_p1.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word7 ( decoder_p1.and1_word7 A ) ( decoder_p1.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and1_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and1_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and1_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and1_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and1_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and1_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and1_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and1_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.y0_word0 ( decoder_p2.and1_word0 A ) ( decoder_p2.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word1 ( decoder_p2.and1_word1 A ) ( decoder_p2.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word2 ( decoder_p2.and1_word2 A ) ( decoder_p2.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word3 ( decoder_p2.and1_word3 A ) ( decoder_p2.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word4 ( decoder_p2.and1_word4 A ) ( decoder_p2.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word5 ( decoder_p2.and1_word5 A ) ( decoder_p2.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word6 ( decoder_p2.and1_word6 A ) ( decoder_p2.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word7 ( decoder_p2.and1_word7 A ) ( decoder_p2.and0_word7 Y ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_p0_b7.aoi_r0_w0 A2 ) ( read_p0_b7.aoi_r0_w0 A1 ) ( read_p0_b6.aoi_r0_w0 A2 ) ( read_p0_b6.aoi_r0_w0 A1 ) ( read_p0_b5.aoi_r0_w0 A2 ) ( read_p0_b5.aoi_r0_w0 A1 ) ++ ( read_p0_b4.aoi_r0_w0 A2 ) ( read_p0_b4.aoi_r0_w0 A1 ) ( read_p0_b3.aoi_r0_w0 A2 ) ( read_p0_b3.aoi_r0_w0 A1 ) ( read_p0_b2.aoi_r0_w0 A2 ) ( read_p0_b2.aoi_r0_w0 A1 ) ( read_p0_b1.aoi_r0_w0 A2 ) ( read_p0_b1.aoi_r0_w0 A1 ) ++ ( read_p0_b0.aoi_r0_w0 A2 ) ( read_p0_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_p0_b7.aoi_r0_w1 A1 ) ( read_p0_b6.aoi_r0_w1 A1 ) ( read_p0_b5.aoi_r0_w1 A1 ) ( read_p0_b4.aoi_r0_w1 A1 ) ( read_p0_b3.aoi_r0_w1 A1 ) ( read_p0_b2.aoi_r0_w1 A1 ) ++ ( read_p0_b1.aoi_r0_w1 A1 ) ( read_p0_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_p0_b7.aoi_r0_w0 B1 ) ( read_p0_b6.aoi_r0_w0 B1 ) ( read_p0_b5.aoi_r0_w0 B1 ) ( read_p0_b4.aoi_r0_w0 B1 ) ( read_p0_b3.aoi_r0_w0 B1 ) ( read_p0_b2.aoi_r0_w0 B1 ) ++ ( read_p0_b1.aoi_r0_w0 B1 ) ( read_p0_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_p0_b7.aoi_r0_w1 B1 ) ( read_p0_b6.aoi_r0_w1 B1 ) ( read_p0_b5.aoi_r0_w1 B1 ) ( read_p0_b4.aoi_r0_w1 B1 ) ( read_p0_b3.aoi_r0_w1 B1 ) ( read_p0_b2.aoi_r0_w1 B1 ) ++ ( read_p0_b1.aoi_r0_w1 B1 ) ( read_p0_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_p0_b7.aoi_r2_w0 A1 ) ( read_p0_b6.aoi_r2_w0 A1 ) ( read_p0_b5.aoi_r2_w0 A1 ) ( read_p0_b4.aoi_r2_w0 A1 ) ( read_p0_b3.aoi_r2_w0 A1 ) ( read_p0_b2.aoi_r2_w0 A1 ) ++ ( read_p0_b1.aoi_r2_w0 A1 ) ( read_p0_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_p0_b7.aoi_r2_w1 A1 ) ( read_p0_b6.aoi_r2_w1 A1 ) ( read_p0_b5.aoi_r2_w1 A1 ) ( read_p0_b4.aoi_r2_w1 A1 ) ( read_p0_b3.aoi_r2_w1 A1 ) ( read_p0_b2.aoi_r2_w1 A1 ) ++ ( read_p0_b1.aoi_r2_w1 A1 ) ( read_p0_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_p0_b7.aoi_r2_w0 B1 ) ( read_p0_b6.aoi_r2_w0 B1 ) ( read_p0_b5.aoi_r2_w0 B1 ) ( read_p0_b4.aoi_r2_w0 B1 ) ( read_p0_b3.aoi_r2_w0 B1 ) ( read_p0_b2.aoi_r2_w0 B1 ) ++ ( read_p0_b1.aoi_r2_w0 B1 ) ( read_p0_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_p0_b7.aoi_r2_w1 B1 ) ( read_p0_b6.aoi_r2_w1 B1 ) ( read_p0_b5.aoi_r2_w1 B1 ) ( read_p0_b4.aoi_r2_w1 B1 ) ( read_p0_b3.aoi_r2_w1 B1 ) ( read_p0_b2.aoi_r2_w1 B1 ) ++ ( read_p0_b1.aoi_r2_w1 B1 ) ( read_p0_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_p1_b7.aoi_r0_w0 A2 ) ( read_p1_b7.aoi_r0_w0 A1 ) ( read_p1_b6.aoi_r0_w0 A2 ) ( read_p1_b6.aoi_r0_w0 A1 ) ( read_p1_b5.aoi_r0_w0 A2 ) ( read_p1_b5.aoi_r0_w0 A1 ) ++ ( read_p1_b4.aoi_r0_w0 A2 ) ( read_p1_b4.aoi_r0_w0 A1 ) ( read_p1_b3.aoi_r0_w0 A2 ) ( read_p1_b3.aoi_r0_w0 A1 ) ( read_p1_b2.aoi_r0_w0 A2 ) ( read_p1_b2.aoi_r0_w0 A1 ) ( read_p1_b1.aoi_r0_w0 A2 ) ( read_p1_b1.aoi_r0_w0 A1 ) ++ ( read_p1_b0.aoi_r0_w0 A2 ) ( read_p1_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_p1_b7.aoi_r0_w1 A1 ) ( read_p1_b6.aoi_r0_w1 A1 ) ( read_p1_b5.aoi_r0_w1 A1 ) ( read_p1_b4.aoi_r0_w1 A1 ) ( read_p1_b3.aoi_r0_w1 A1 ) ( read_p1_b2.aoi_r0_w1 A1 ) ++ ( read_p1_b1.aoi_r0_w1 A1 ) ( read_p1_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_p1_b7.aoi_r0_w0 B1 ) ( read_p1_b6.aoi_r0_w0 B1 ) ( read_p1_b5.aoi_r0_w0 B1 ) ( read_p1_b4.aoi_r0_w0 B1 ) ( read_p1_b3.aoi_r0_w0 B1 ) ( read_p1_b2.aoi_r0_w0 B1 ) ++ ( read_p1_b1.aoi_r0_w0 B1 ) ( read_p1_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_p1_b7.aoi_r0_w1 B1 ) ( read_p1_b6.aoi_r0_w1 B1 ) ( read_p1_b5.aoi_r0_w1 B1 ) ( read_p1_b4.aoi_r0_w1 B1 ) ( read_p1_b3.aoi_r0_w1 B1 ) ( read_p1_b2.aoi_r0_w1 B1 ) ++ ( read_p1_b1.aoi_r0_w1 B1 ) ( read_p1_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_p1_b7.aoi_r2_w0 A1 ) ( read_p1_b6.aoi_r2_w0 A1 ) ( read_p1_b5.aoi_r2_w0 A1 ) ( read_p1_b4.aoi_r2_w0 A1 ) ( read_p1_b3.aoi_r2_w0 A1 ) ( read_p1_b2.aoi_r2_w0 A1 ) ++ ( read_p1_b1.aoi_r2_w0 A1 ) ( read_p1_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_p1_b7.aoi_r2_w1 A1 ) ( read_p1_b6.aoi_r2_w1 A1 ) ( read_p1_b5.aoi_r2_w1 A1 ) ( read_p1_b4.aoi_r2_w1 A1 ) ( read_p1_b3.aoi_r2_w1 A1 ) ( read_p1_b2.aoi_r2_w1 A1 ) ++ ( read_p1_b1.aoi_r2_w1 A1 ) ( read_p1_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_p1_b7.aoi_r2_w0 B1 ) ( read_p1_b6.aoi_r2_w0 B1 ) ( read_p1_b5.aoi_r2_w0 B1 ) ( read_p1_b4.aoi_r2_w0 B1 ) ( read_p1_b3.aoi_r2_w0 B1 ) ( read_p1_b2.aoi_r2_w0 B1 ) ++ ( read_p1_b1.aoi_r2_w0 B1 ) ( read_p1_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_p1_b7.aoi_r2_w1 B1 ) ( read_p1_b6.aoi_r2_w1 B1 ) ( read_p1_b5.aoi_r2_w1 B1 ) ( read_p1_b4.aoi_r2_w1 B1 ) ( read_p1_b3.aoi_r2_w1 B1 ) ( read_p1_b2.aoi_r2_w1 B1 ) ++ ( read_p1_b1.aoi_r2_w1 B1 ) ( read_p1_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - read_p0_b0.t0_2 ( read_p0_b0.nand_r0_4 A ) ( read_p0_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b0.t0_4 ( read_p0_b0.nor_r0_8 A ) ( read_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b0.t2_4 ( read_p0_b0.aoi_r2_w0 Y ) ( read_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b0.t4_6 ( read_p0_b0.nand_r4_8 A ) ( read_p0_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b0.t4_8 ( read_p0_b0.nor_r0_8 B ) ( read_p0_b0.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b0.t6_8 ( read_p0_b0.aoi_r2_w1 Y ) ( read_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b1.t0_2 ( read_p0_b1.nand_r0_4 A ) ( read_p0_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b1.t0_4 ( read_p0_b1.nor_r0_8 A ) ( read_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b1.t2_4 ( read_p0_b1.aoi_r2_w0 Y ) ( read_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b1.t4_6 ( read_p0_b1.nand_r4_8 A ) ( read_p0_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b1.t4_8 ( read_p0_b1.nor_r0_8 B ) ( read_p0_b1.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b1.t6_8 ( read_p0_b1.aoi_r2_w1 Y ) ( read_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b2.t0_2 ( read_p0_b2.nand_r0_4 A ) ( read_p0_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b2.t0_4 ( read_p0_b2.nor_r0_8 A ) ( read_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b2.t2_4 ( read_p0_b2.aoi_r2_w0 Y ) ( read_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b2.t4_6 ( read_p0_b2.nand_r4_8 A ) ( read_p0_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b2.t4_8 ( read_p0_b2.nor_r0_8 B ) ( read_p0_b2.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b2.t6_8 ( read_p0_b2.aoi_r2_w1 Y ) ( read_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b3.t0_2 ( read_p0_b3.nand_r0_4 A ) ( read_p0_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b3.t0_4 ( read_p0_b3.nor_r0_8 A ) ( read_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b3.t2_4 ( read_p0_b3.aoi_r2_w0 Y ) ( read_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b3.t4_6 ( read_p0_b3.nand_r4_8 A ) ( read_p0_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b3.t4_8 ( read_p0_b3.nor_r0_8 B ) ( read_p0_b3.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b3.t6_8 ( read_p0_b3.aoi_r2_w1 Y ) ( read_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b4.t0_2 ( read_p0_b4.nand_r0_4 A ) ( read_p0_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b4.t0_4 ( read_p0_b4.nor_r0_8 A ) ( read_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b4.t2_4 ( read_p0_b4.aoi_r2_w0 Y ) ( read_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b4.t4_6 ( read_p0_b4.nand_r4_8 A ) ( read_p0_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b4.t4_8 ( read_p0_b4.nor_r0_8 B ) ( read_p0_b4.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b4.t6_8 ( read_p0_b4.aoi_r2_w1 Y ) ( read_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b5.t0_2 ( read_p0_b5.nand_r0_4 A ) ( read_p0_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b5.t0_4 ( read_p0_b5.nor_r0_8 A ) ( read_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b5.t2_4 ( read_p0_b5.aoi_r2_w0 Y ) ( read_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b5.t4_6 ( read_p0_b5.nand_r4_8 A ) ( read_p0_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b5.t4_8 ( read_p0_b5.nor_r0_8 B ) ( read_p0_b5.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b5.t6_8 ( read_p0_b5.aoi_r2_w1 Y ) ( read_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b6.t0_2 ( read_p0_b6.nand_r0_4 A ) ( read_p0_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b6.t0_4 ( read_p0_b6.nor_r0_8 A ) ( read_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b6.t2_4 ( read_p0_b6.aoi_r2_w0 Y ) ( read_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b6.t4_6 ( read_p0_b6.nand_r4_8 A ) ( read_p0_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b6.t4_8 ( read_p0_b6.nor_r0_8 B ) ( read_p0_b6.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b6.t6_8 ( read_p0_b6.aoi_r2_w1 Y ) ( read_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b7.t0_2 ( read_p0_b7.nand_r0_4 A ) ( read_p0_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b7.t0_4 ( read_p0_b7.nor_r0_8 A ) ( read_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b7.t2_4 ( read_p0_b7.aoi_r2_w0 Y ) ( read_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b7.t4_6 ( read_p0_b7.nand_r4_8 A ) ( read_p0_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b7.t4_8 ( read_p0_b7.nor_r0_8 B ) ( read_p0_b7.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b7.t6_8 ( read_p0_b7.aoi_r2_w1 Y ) ( read_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b0.t0_2 ( read_p1_b0.nand_r0_4 A ) ( read_p1_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b0.t0_4 ( read_p1_b0.nor_r0_8 A ) ( read_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b0.t2_4 ( read_p1_b0.aoi_r2_w0 Y ) ( read_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b0.t4_6 ( read_p1_b0.nand_r4_8 A ) ( read_p1_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b0.t4_8 ( read_p1_b0.nor_r0_8 B ) ( read_p1_b0.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b0.t6_8 ( read_p1_b0.aoi_r2_w1 Y ) ( read_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b1.t0_2 ( read_p1_b1.nand_r0_4 A ) ( read_p1_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b1.t0_4 ( read_p1_b1.nor_r0_8 A ) ( read_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b1.t2_4 ( read_p1_b1.aoi_r2_w0 Y ) ( read_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b1.t4_6 ( read_p1_b1.nand_r4_8 A ) ( read_p1_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b1.t4_8 ( read_p1_b1.nor_r0_8 B ) ( read_p1_b1.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b1.t6_8 ( read_p1_b1.aoi_r2_w1 Y ) ( read_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b2.t0_2 ( read_p1_b2.nand_r0_4 A ) ( read_p1_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b2.t0_4 ( read_p1_b2.nor_r0_8 A ) ( read_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b2.t2_4 ( read_p1_b2.aoi_r2_w0 Y ) ( read_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b2.t4_6 ( read_p1_b2.nand_r4_8 A ) ( read_p1_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b2.t4_8 ( read_p1_b2.nor_r0_8 B ) ( read_p1_b2.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b2.t6_8 ( read_p1_b2.aoi_r2_w1 Y ) ( read_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b3.t0_2 ( read_p1_b3.nand_r0_4 A ) ( read_p1_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b3.t0_4 ( read_p1_b3.nor_r0_8 A ) ( read_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b3.t2_4 ( read_p1_b3.aoi_r2_w0 Y ) ( read_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b3.t4_6 ( read_p1_b3.nand_r4_8 A ) ( read_p1_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b3.t4_8 ( read_p1_b3.nor_r0_8 B ) ( read_p1_b3.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b3.t6_8 ( read_p1_b3.aoi_r2_w1 Y ) ( read_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b4.t0_2 ( read_p1_b4.nand_r0_4 A ) ( read_p1_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b4.t0_4 ( read_p1_b4.nor_r0_8 A ) ( read_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b4.t2_4 ( read_p1_b4.aoi_r2_w0 Y ) ( read_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b4.t4_6 ( read_p1_b4.nand_r4_8 A ) ( read_p1_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b4.t4_8 ( read_p1_b4.nor_r0_8 B ) ( read_p1_b4.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b4.t6_8 ( read_p1_b4.aoi_r2_w1 Y ) ( read_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b5.t0_2 ( read_p1_b5.nand_r0_4 A ) ( read_p1_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b5.t0_4 ( read_p1_b5.nor_r0_8 A ) ( read_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b5.t2_4 ( read_p1_b5.aoi_r2_w0 Y ) ( read_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b5.t4_6 ( read_p1_b5.nand_r4_8 A ) ( read_p1_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b5.t4_8 ( read_p1_b5.nor_r0_8 B ) ( read_p1_b5.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b5.t6_8 ( read_p1_b5.aoi_r2_w1 Y ) ( read_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b6.t0_2 ( read_p1_b6.nand_r0_4 A ) ( read_p1_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b6.t0_4 ( read_p1_b6.nor_r0_8 A ) ( read_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b6.t2_4 ( read_p1_b6.aoi_r2_w0 Y ) ( read_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b6.t4_6 ( read_p1_b6.nand_r4_8 A ) ( read_p1_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b6.t4_8 ( read_p1_b6.nor_r0_8 B ) ( read_p1_b6.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b6.t6_8 ( read_p1_b6.aoi_r2_w1 Y ) ( read_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b7.t0_2 ( read_p1_b7.nand_r0_4 A ) ( read_p1_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b7.t0_4 ( read_p1_b7.nor_r0_8 A ) ( read_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b7.t2_4 ( read_p1_b7.aoi_r2_w0 Y ) ( read_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b7.t4_6 ( read_p1_b7.nand_r4_8 A ) ( read_p1_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b7.t4_8 ( read_p1_b7.nor_r0_8 B ) ( read_p1_b7.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b7.t6_8 ( read_p1_b7.aoi_r2_w1 Y ) ( read_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_1_0.bit0.storage ( read_p1_b0.aoi_r0_w1 A2 ) ( read_p0_b0.aoi_r0_w1 A2 ) ( storage_0_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit1.storage ( read_p1_b1.aoi_r0_w1 A2 ) ( read_p0_b1.aoi_r0_w1 A2 ) ( storage_0_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit2.storage ( read_p1_b2.aoi_r0_w1 A2 ) ( read_p0_b2.aoi_r0_w1 A2 ) ( storage_0_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit3.storage ( read_p1_b3.aoi_r0_w1 A2 ) ( read_p0_b3.aoi_r0_w1 A2 ) ( storage_0_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit4.storage ( read_p1_b4.aoi_r0_w1 A2 ) ( read_p0_b4.aoi_r0_w1 A2 ) ( storage_0_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit5.storage ( read_p1_b5.aoi_r0_w1 A2 ) ( read_p0_b5.aoi_r0_w1 A2 ) ( storage_0_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit6.storage ( read_p1_b6.aoi_r0_w1 A2 ) ( read_p0_b6.aoi_r0_w1 A2 ) ( storage_0_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit7.storage ( read_p1_b7.aoi_r0_w1 A2 ) ( read_p0_b7.aoi_r0_w1 A2 ) ( storage_0_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.gclock ( storage_0_1_0.cg GCLK ) ( storage_0_1_0.bit7.bit CLK ) ( storage_0_1_0.bit6.bit CLK ) ( storage_0_1_0.bit5.bit CLK ) ( storage_0_1_0.bit4.bit CLK ) ( storage_0_1_0.bit3.bit CLK ) ( storage_0_1_0.bit2.bit CLK ) ++ ( storage_0_1_0.bit1.bit CLK ) ( storage_0_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_1_0.we ( storage_0_1_0.gcand Y ) ( storage_0_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_p1_b0.aoi_r0_w0 B2 ) ( read_p0_b0.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_p1_b1.aoi_r0_w0 B2 ) ( read_p0_b1.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_p1_b2.aoi_r0_w0 B2 ) ( read_p0_b2.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_p1_b3.aoi_r0_w0 B2 ) ( read_p0_b3.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_p1_b4.aoi_r0_w0 B2 ) ( read_p0_b4.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_p1_b5.aoi_r0_w0 B2 ) ( read_p0_b5.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_p1_b6.aoi_r0_w0 B2 ) ( read_p0_b6.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_p1_b7.aoi_r0_w0 B2 ) ( read_p0_b7.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_1_0.bit0.storage ( storage_1_1_0.bit0.bit QN ) ( read_p1_b0.aoi_r0_w1 B2 ) ( read_p0_b0.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit1.storage ( storage_1_1_0.bit1.bit QN ) ( read_p1_b1.aoi_r0_w1 B2 ) ( read_p0_b1.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit2.storage ( storage_1_1_0.bit2.bit QN ) ( read_p1_b2.aoi_r0_w1 B2 ) ( read_p0_b2.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit3.storage ( storage_1_1_0.bit3.bit QN ) ( read_p1_b3.aoi_r0_w1 B2 ) ( read_p0_b3.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit4.storage ( storage_1_1_0.bit4.bit QN ) ( read_p1_b4.aoi_r0_w1 B2 ) ( read_p0_b4.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit5.storage ( storage_1_1_0.bit5.bit QN ) ( read_p1_b5.aoi_r0_w1 B2 ) ( read_p0_b5.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit6.storage ( storage_1_1_0.bit6.bit QN ) ( read_p1_b6.aoi_r0_w1 B2 ) ( read_p0_b6.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit7.storage ( storage_1_1_0.bit7.bit QN ) ( read_p1_b7.aoi_r0_w1 B2 ) ( read_p0_b7.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.gclock ( storage_1_1_0.cg GCLK ) ( storage_1_1_0.bit7.bit CLK ) ( storage_1_1_0.bit6.bit CLK ) ( storage_1_1_0.bit5.bit CLK ) ( storage_1_1_0.bit4.bit CLK ) ( storage_1_1_0.bit3.bit CLK ) ( storage_1_1_0.bit2.bit CLK ) ++ ( storage_1_1_0.bit1.bit CLK ) ( storage_1_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_1_0.we ( storage_1_1_0.gcand Y ) ( storage_1_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_p1_b0.aoi_r2_w0 A2 ) ( read_p0_b0.aoi_r2_w0 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_p1_b1.aoi_r2_w0 A2 ) ( read_p0_b1.aoi_r2_w0 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_p1_b2.aoi_r2_w0 A2 ) ( read_p0_b2.aoi_r2_w0 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_p1_b3.aoi_r2_w0 A2 ) ( read_p0_b3.aoi_r2_w0 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_p1_b4.aoi_r2_w0 A2 ) ( read_p0_b4.aoi_r2_w0 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_p1_b5.aoi_r2_w0 A2 ) ( read_p0_b5.aoi_r2_w0 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_p1_b6.aoi_r2_w0 A2 ) ( read_p0_b6.aoi_r2_w0 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_p1_b7.aoi_r2_w0 A2 ) ( read_p0_b7.aoi_r2_w0 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_1_0.bit0.storage ( read_p1_b0.aoi_r2_w1 A2 ) ( read_p0_b0.aoi_r2_w1 A2 ) ( storage_2_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit1.storage ( read_p1_b1.aoi_r2_w1 A2 ) ( read_p0_b1.aoi_r2_w1 A2 ) ( storage_2_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit2.storage ( read_p1_b2.aoi_r2_w1 A2 ) ( read_p0_b2.aoi_r2_w1 A2 ) ( storage_2_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit3.storage ( read_p1_b3.aoi_r2_w1 A2 ) ( read_p0_b3.aoi_r2_w1 A2 ) ( storage_2_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit4.storage ( read_p1_b4.aoi_r2_w1 A2 ) ( read_p0_b4.aoi_r2_w1 A2 ) ( storage_2_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit5.storage ( read_p1_b5.aoi_r2_w1 A2 ) ( read_p0_b5.aoi_r2_w1 A2 ) ( storage_2_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit6.storage ( read_p1_b6.aoi_r2_w1 A2 ) ( read_p0_b6.aoi_r2_w1 A2 ) ( storage_2_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit7.storage ( read_p1_b7.aoi_r2_w1 A2 ) ( read_p0_b7.aoi_r2_w1 A2 ) ( storage_2_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.gclock ( storage_2_1_0.cg GCLK ) ( storage_2_1_0.bit7.bit CLK ) ( storage_2_1_0.bit6.bit CLK ) ( storage_2_1_0.bit5.bit CLK ) ( storage_2_1_0.bit4.bit CLK ) ( storage_2_1_0.bit3.bit CLK ) ( storage_2_1_0.bit2.bit CLK ) ++ ( storage_2_1_0.bit1.bit CLK ) ( storage_2_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_1_0.we ( storage_2_1_0.gcand Y ) ( storage_2_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_p1_b0.aoi_r2_w0 B2 ) ( read_p0_b0.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_p1_b1.aoi_r2_w0 B2 ) ( read_p0_b1.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_p1_b2.aoi_r2_w0 B2 ) ( read_p0_b2.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_p1_b3.aoi_r2_w0 B2 ) ( read_p0_b3.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_p1_b4.aoi_r2_w0 B2 ) ( read_p0_b4.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_p1_b5.aoi_r2_w0 B2 ) ( read_p0_b5.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_p1_b6.aoi_r2_w0 B2 ) ( read_p0_b6.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_p1_b7.aoi_r2_w0 B2 ) ( read_p0_b7.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_1_0.bit0.storage ( storage_3_1_0.bit0.bit QN ) ( read_p1_b0.aoi_r2_w1 B2 ) ( read_p0_b0.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit1.storage ( storage_3_1_0.bit1.bit QN ) ( read_p1_b1.aoi_r2_w1 B2 ) ( read_p0_b1.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit2.storage ( storage_3_1_0.bit2.bit QN ) ( read_p1_b2.aoi_r2_w1 B2 ) ( read_p0_b2.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit3.storage ( storage_3_1_0.bit3.bit QN ) ( read_p1_b3.aoi_r2_w1 B2 ) ( read_p0_b3.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit4.storage ( storage_3_1_0.bit4.bit QN ) ( read_p1_b4.aoi_r2_w1 B2 ) ( read_p0_b4.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit5.storage ( storage_3_1_0.bit5.bit QN ) ( read_p1_b5.aoi_r2_w1 B2 ) ( read_p0_b5.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit6.storage ( storage_3_1_0.bit6.bit QN ) ( read_p1_b6.aoi_r2_w1 B2 ) ( read_p0_b6.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit7.storage ( storage_3_1_0.bit7.bit QN ) ( read_p1_b7.aoi_r2_w1 B2 ) ( read_p0_b7.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.gclock ( storage_3_1_0.cg GCLK ) ( storage_3_1_0.bit7.bit CLK ) ( storage_3_1_0.bit6.bit CLK ) ( storage_3_1_0.bit5.bit CLK ) ( storage_3_1_0.bit4.bit CLK ) ( storage_3_1_0.bit3.bit CLK ) ( storage_3_1_0.bit2.bit CLK ) ++ ( storage_3_1_0.bit1.bit CLK ) ( storage_3_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_1_0.we ( storage_3_1_0.gcand Y ) ( storage_3_1_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_0_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_1_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_2_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_3_1_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_3_1_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_1_0.gcand B ) ( storage_2_0_0.gcand B ) ( storage_1_1_0.gcand B ) ( storage_1_0_0.gcand B ) ++ ( storage_0_1_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_banks_asap7.tcl b/src/ram/test/make_8x8_2r1w_banks_asap7.tcl +new file mode 100644 +index 0000000000..6a79bb37da +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_banks_asap7.tcl +@@ -0,0 +1,36 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees over 4 interleaved banks, 2 side by side, each word decoded ++# whole, and word 0 reads 0. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_banks_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -banks 4 \ ++ -bank_columns 2 \ ++ -bank_order interleaved \ ++ -zero_word 0 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_banks_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_banks_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_banks_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_banks_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_banks_asap7_behavioral.vok +new file mode 100644 +index 0000000000..373f465efb +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_banks_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i] && addr_w != 0) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = addr_r0 == 0 ? 8'd0 : mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = addr_r1 == 0 ? 8'd0 : mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index ccfe40b181..de4890a1af 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -9,5 +9,6 @@ record_tests { + make_8x8_2r1w_and_or_asap7 + make_8x8_2r1w_zero_asap7 + make_8x8_2r1w_reset_asap7 ++ make_8x8_2r1w_banks_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 8342b9244..0653fc454 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -175,6 +175,7 @@ test_suite( "@openroad//src/ram/test:make_7x7_2r1w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_and_or_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_banks_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_reset_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 99d0b2810..8ac1c75dd 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -157,7 +157,9 @@ ASAP7 = { # flop (the storage cell named: the smallest flop is negative-edge), and # with a word reading 0 (patch 0013), on either polarity of flop; and # with an asynchronous reset to a value of both 0s and 1s (patch 0014), -# on Nangate45's set/reset flop and asap7's, which stores !D. +# on Nangate45's set/reset flop and asap7's, which stores !D; and in +# banks (patch 0015), contiguous and interleaved, side by side and +# stacked, tristate and AND-OR, and 12 words in banks of 3. [ [ genrule( @@ -171,7 +173,7 @@ ASAP7 = { cat > $(@D)/{name}.tcl < $(@D)/{name}.log 2>&1 || {{ cat $(@D)/{name}.log; exit 1; }} @@ -183,19 +185,21 @@ read_db $(@D)/{name}.odb write_verilog $(@D)/{name}.v TCL $(location @openroad//:openroad) -exit -no_init -no_splash $(@D)/{name}_v.tcl >> $(@D)/{name}.log 2>&1 || {{ cat $(@D)/{name}.log; exit 1; }} -sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_gen.v) +sed -e 's/^module RAM{words}x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_gen.v) +sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) """.format( name = name, args = args, read_lefs = "\n".join(["read_lef $(location %s)" % f for f in platform["lefs"]]), read_libs = "\n".join(["read_liberty $(location %s)" % f for f in platform["libs"]]), + words = words, ), tools = ["@openroad"], ), verilog_library( name = "tb_%s_rtl" % name, srcs = [ - "%s.v" % tb, + ("%s.v" % tb) if words == 8 else ("%s_%d.v" % (tb, words)), ":%s_gen.v" % name, ":%s_model.v" % name, ] + platform["stdcell"], @@ -215,17 +219,23 @@ sed 's/^module RAM8x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_g name = "%s_sim_test" % name, size = "small", srcs = ["%s.cc" % tb], + defines = ["WORDS=%d" % words], deps = [":tb_%s" % name], ), ] - for name, platform, args, tb in [ - ("ram_2w", NANGATE45, "-storage_cell DFF_X1", "tb_ram_2w"), - ("ram_2w_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or", "tb_ram_2w"), - ("ram_2w_and_or_zero", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -zero_word 3", "tb_ram_2w"), - ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R", "tb_ram_2w"), - ("ram_2w_asap7_zero", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -zero_word 0", "tb_ram_2w"), - ("ram_2w_rst", NANGATE45, "-storage_cell DFFRS_X1 -reset_value 0xa5", "tb_ram_2w_rst"), - ("ram_2w_rst_and_or", NANGATE45, "-storage_cell DFFRS_X1 -read_style and_or -reset_value 0xa5", "tb_ram_2w_rst"), - ("ram_2w_rst_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -reset_value 0xa5", "tb_ram_2w_rst"), + for name, platform, args, tb, words in [ + ("ram_2w", NANGATE45, "-storage_cell DFF_X1", "tb_ram_2w", 8), + ("ram_2w_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or", "tb_ram_2w", 8), + ("ram_2w_and_or_zero", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -zero_word 3", "tb_ram_2w", 8), + ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R", "tb_ram_2w", 8), + ("ram_2w_asap7_zero", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -zero_word 0", "tb_ram_2w", 8), + ("ram_2w_rst", NANGATE45, "-storage_cell DFFRS_X1 -reset_value 0xa5", "tb_ram_2w_rst", 8), + ("ram_2w_rst_and_or", NANGATE45, "-storage_cell DFFRS_X1 -read_style and_or -reset_value 0xa5", "tb_ram_2w_rst", 8), + ("ram_2w_rst_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -reset_value 0xa5", "tb_ram_2w_rst", 8), + ("ram_2w_banks", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 2 -bank_order interleaved", "tb_ram_2w", 8), + ("ram_2w_banks_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -banks 2 -bank_columns 2", "tb_ram_2w", 8), + ("ram_2w_banks_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2 -bank_order interleaved -zero_word 0", "tb_ram_2w", 8), + ("ram_2w_banks12_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2", "tb_ram_2w", 12), + ("ram_2w_banks12", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 4 -bank_order interleaved", "tb_ram_2w", 12), ] ] diff --git a/test/regfile/sim/tb_ram_2w.cc b/test/regfile/sim/tb_ram_2w.cc index d693d5317..e49cc1954 100644 --- a/test/regfile/sim/tb_ram_2w.cc +++ b/test/regfile/sim/tb_ram_2w.cc @@ -9,6 +9,10 @@ #include "Vtb_ram_2w.h" +#ifndef WORDS +#define WORDS 8 +#endif + int main() { Vtb_ram_2w tb; std::mt19937 rng(1); @@ -34,14 +38,14 @@ int main() { tb.eval(); ++cycle; }; - for (int w = 0; w < 8; ++w) { + for (int w = 0; w < WORDS; ++w) { step(false, true, w, rng() & 0xff, false, 0, 0, w); } for (int i = 0; i < 20000 && bad < 10; ++i) { - const int a0 = rng() % 8; - const int a1 = rng() % 4 == 0 ? a0 : rng() % 8; + const int a0 = rng() % WORDS; + const int a1 = rng() % 4 == 0 ? a0 : rng() % WORDS; step(true, rng() % 2, a0, rng() & 0xff, rng() % 2, a1, rng() & 0xff, - rng() % 8); + rng() % WORDS); } std::printf("%d cycles, %d mismatches\n", cycle, bad); return bad == 0 ? 0 : 1; diff --git a/test/regfile/sim/tb_ram_2w_12.v b/test/regfile/sim/tb_ram_2w_12.v new file mode 100644 index 000000000..2d3107ae3 --- /dev/null +++ b/test/regfile/sim/tb_ram_2w_12.v @@ -0,0 +1,23 @@ +// generate_ram with two write ports and one read port: its behavioral +// model (RAM8x8) and its netlist (RAM8x8_gen) on the same inputs. +module tb_ram_2w ( + input clk, + input [7:0] D0, + input [7:0] D1, + input [3:0] addr_w0, + input [3:0] addr_w1, + input [3:0] addr_r0, + input we0, + input we1, + output [7:0] Q_model, + output [7:0] Q_gen +); + RAM8x8 model ( + .clk(clk), .D0(D0), .D1(D1), .Q(Q_model), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1) + ); + RAM8x8_gen gen ( + .clk(clk), .D0(D0), .D1(D1), .Q(Q_gen), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1) + ); +endmodule From ded328c9752595c03765d8c59b071af240324803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 09:06:40 +0200 Subject: [PATCH 15/26] ram: generate_ram -rb_ports, banked read ports (patch 0016) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sixth generate_regfile feature carried onto generate_ram, on 0015: -rb_ports n adds read ports with an address and a data output per bank, each bank read independently in the same cycle, as XiangShan's integer register file reads. Each (port, bank) is a read port of its own to the generator, decoding and reading only its bank's words. Tests: make_8x8_rb_asap7 in generate_ram's format; a plain and a banked read port simulated against the behavioral model on Nangate45 (interleaved, tristate) and asap7 (contiguous, AND-OR, zero word), every output every cycle, 20 008 cycles each, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + .../0016-openroad-ram-banked-read-ports.patch | 1225 +++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 5 +- test/regfile/sim/tb_ram_rb.cc | 50 + test/regfile/sim/tb_ram_rb.v | 38 + 6 files changed, 1321 insertions(+), 1 deletion(-) create mode 100644 patches/0016-openroad-ram-banked-read-ports.patch create mode 100644 test/regfile/sim/tb_ram_rb.cc create mode 100644 test/regfile/sim/tb_ram_rb.v diff --git a/MODULE.bazel b/MODULE.bazel index 301fda3ad..6ca23cfbb 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -147,6 +147,9 @@ archive_override( # banks, each word decoded whole. On 0014 (OpenROAD #11669); not # upstreamed. "//patches:0015-openroad-ram-banks.patch", + # 0016: generate_ram -rb_ports, read ports with an address and data + # per bank. On 0015 (OpenROAD #11669); not upstreamed. + "//patches:0016-openroad-ram-banked-read-ports.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0016-openroad-ram-banked-read-ports.patch b/patches/0016-openroad-ram-banked-read-ports.patch new file mode 100644 index 000000000..297c11b06 --- /dev/null +++ b/patches/0016-openroad-ram-banked-read-ports.patch @@ -0,0 +1,1225 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -rb_ports, banked read ports + +-rb_ports n adds n banked read ports to a RAM with -banks: each has an +address and a data output per bank (addr_rb_b, Qrb_b), the +address the word's index in its bank, every bank read independently in +the same cycle, as XiangShan's integer register file reads. To the +generator below, each (port, bank) is a read port of its own that +decodes and reads only its bank's words: a tristate bitline or an +AND-OR tree over them. The behavioral model reads the same words. + +The sixth of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 8fabb35c70..5f4dcdaa51 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -49,6 +49,7 @@ generate_ram [-mask_size bits] + [-banks count] + [-bank_columns count] + [-bank_order contiguous|interleaved] ++ [-rb_ports count] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -78,6 +79,7 @@ generate_ram [-mask_size bits] + | `-zero_word` | A word that reads 0 and drops its writes, as a RISC-V register file's x0: its row has no flops or clock gate, and the read trees leave it out. Needs `-read_style and_or` and `-column_mux_ratio 1`. Default: none. | + | `-reset_value` | Resets every word to `value` asynchronously, through a reset port at the storage flop's own polarity (`rst_n` or `rst`); each bit's flop is cleared or preset, the other pin held off. The storage cell has both an asynchronous clear and preset. A parent adapts a reset of another polarity, or a synchronous one, to it. Not with `-use_latch`. Default: no reset. | + | `-banks`, `-bank_columns`, `-bank_order` | The words in `banks` banks, contiguous or interleaved in the address, `bank_columns` of them side by side and the rest stacked. With banks each port decodes every word's whole address, so a bank need not be a power of two words. Not with `-column_mux_ratio` above 1 or `-use_latch`. Default: one bank. | ++| `-rb_ports` | Banked read ports, with `-banks`: each an address and a data output per bank (`addr_rb_b`, `Qrb_b`), the address the word's index in its bank, every bank read independently. Default: 0. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index c0d47bbf92..6d9e6253d3 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -115,7 +115,8 @@ class RamGen + const std::string& reset_value = "", + int banks = 1, + int bank_columns = 1, +- const std::string& bank_order = "contiguous"); ++ const std::string& bank_order = "contiguous", ++ int rb_ports = 0); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -354,6 +355,13 @@ class RamGen + bool bank_interleaved_{false}; + int words_per_bank_{0}; + int words_per_row_{1}; ++ // Banked read ports: each an address and a data output per bank, read ++ // independently (rb_ports_ of them, after the plain read ports) ++ int rb_ports_{0}; ++ int r_plain_{0}; // the plain read ports, read/write ones included ++ // the bank of the word at (row, word in the row), and its index there ++ int bankAt(int row, int word_idx) const; ++ int indexInBank(int row) const; + // An asynchronous reset to reset_value_ (a word's value, every word): + // each bit's flop is cleared or preset by the reset port, the other + // pin held off. The pins come from the flop's ff group; clear_reads_ +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 43a2724490..9d75d28322 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -152,6 +152,9 @@ std::unique_ptr RamGen::makeBit(const std::string& prefix, + } + + for (int read_port = 0; read_port < read_ports; ++read_port) { ++ if (select[read_port] == nullptr) { ++ continue; // a banked read port's other banks ++ } + makeInst( + bit_cell.get(), + prefix, +@@ -186,6 +189,16 @@ bool RamGen::treeInverted(const int lo, const int hi) const + return !treeInverted(lo, lo + half); + } + ++int RamGen::bankAt(const int row, const int word_idx) const ++{ ++ return (row / words_per_bank_) * bank_columns_ + word_idx; ++} ++ ++int RamGen::indexInBank(const int row) const ++{ ++ return row % words_per_bank_; ++} ++ + int RamGen::wordAt(const int row, const int word_idx) const + { + if (!banked_) { +@@ -347,7 +360,9 @@ void RamGen::makeSlice(const int slice_idx, + // the AND-OR trees read the true selects + } else if (column_mux_ratio == 1 || banked_) { + for (int i = 0; i < r_total; ++i) { +- select_b_nets[i] = makeNet(prefix, fmt::format("select{}_b", i)); ++ if (selects[num_write + i] != nullptr) { ++ select_b_nets[i] = makeNet(prefix, fmt::format("select{}_b", i)); ++ } + } + } else { + select_b_nets = shared_select_b_nets; +@@ -556,6 +571,9 @@ void RamGen::makeSlice(const int slice_idx, + // Make select inverters + if (create_select_inv && !and_or_read_) { + for (int i = 0; i < r_total; ++i) { ++ if (selects[num_write + i] == nullptr) { ++ continue; // a banked read port's other banks ++ } + makeInst(sel_cell.get(), + prefix, + fmt::format("select_inv_{}", i), +@@ -704,6 +722,9 @@ void RamGen::makeBufferColumn(const std::string& prefix, + // a buffer per select: one per row, or with banks one per word + for (int k = 0; k < words_per_row; ++k) { + const int word = row * words_per_row + k; ++ if (decoder_output_nets[word] == nullptr) { ++ continue; // a banked read port's other banks ++ } + makeInst( + buf_cell.get(), + prefix, +@@ -729,6 +750,9 @@ void RamGen::makeWordDecoderColumn( + auto row_cell = std::make_unique(); + for (int k = 0; k < words_per_row; ++k) { + const int word = row * words_per_row + k; ++ if (literals[word].empty()) { ++ continue; // a banked read port's other banks ++ } + // a balanced AND2 tree over the word's address literals + vector level = literals[word]; + int node = 0; +@@ -788,6 +812,12 @@ std::unique_ptr RamGen::makeInverterColumn( + + for (int bit = num_row_bits - 1; bit >= 0; --bit) { + for (int p = start_port; p < end_port; ++p) { ++ // a banked read port's address is narrower than the others ++ if (num_word_bits + bit ++ >= static_cast(addr_inputs_[p].size())) { ++ cell_inv_layout->addCell(nullptr); ++ continue; ++ } + auto inv_grid_cell = std::make_unique(); + makeInst(inv_grid_cell.get(), + fmt::format("decoder_p{}", p), +@@ -1751,7 +1781,8 @@ void RamGen::generate(const int mask_size, + const std::string& reset_value, + const int banks, + const int bank_columns, +- const std::string& bank_order) ++ const std::string& bank_order, ++ const int rb_ports) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1779,6 +1810,16 @@ void RamGen::generate(const int mask_size, + } + } + words_per_bank_ = num_words / banks_; ++ rb_ports_ = rb_ports; ++ r_plain_ = rw_ports + r_ports; ++ if (rb_ports_ > 0 && !banked_) { ++ logger_->error(RAM, 70, "-rb_ports needs -banks."); ++ } ++ // a banked read port is a read port per bank to the generator below ++ const int r_ports_all = r_ports + rb_ports_ * banks_; ++ // the address bits of a banked read port's per-bank address ++ const int bank_inputs = std::max( ++ 1, static_cast(std::ceil(std::log2(words_per_bank_)))); + // the words in a row: the column mux's, or the banks side by side + const int column_mux_ratio = banked_ ? bank_columns_ : column_mux_ratio_arg; + words_per_row_ = column_mux_ratio; +@@ -1910,7 +1951,7 @@ void RamGen::generate(const int mask_size, + // One column per bit plus one select/control column per slice, + // Each read/write port gets a buffer col and decoder col, + // plus inverter columns shared across ports +- const int total_ports = rw_ports + r_ports + w_ports; ++ const int total_ports = rw_ports + r_ports_all + w_ports; + // at least one port's inverters a column: an array with fewer rows than + // address bits (four banks side by side, say) otherwise got none + const int ports_per_col +@@ -1991,15 +2032,24 @@ void RamGen::generate(const int mask_size, + } else if (p < rw_ports + w_ports) { + port_prefix = num_write == 1 ? "addr_w" : fmt::format("addr_w{}", w_idx); + w_idx++; +- } else { ++ } else if (r_idx < r_ports) { + port_prefix = fmt::format("addr_r{}", r_idx++); ++ } else { ++ // a banked read port's address for one bank ++ const int kb = r_idx++ - r_ports; ++ port_prefix = fmt::format("addr_rb{}_b{}", kb / banks_, kb % banks_); + } + // NOLINTEND(misc-include-cleaner) ++ // a banked read port's bank, or -1 ++ const int port_bank = p >= rw_ports + w_ports + r_ports ++ ? (p - rw_ports - w_ports - r_ports) % banks_ ++ : -1; ++ const int port_inputs = port_bank >= 0 ? bank_inputs : num_inputs; + +- addr_inputs_[p].resize(num_inputs); +- inv_addr_nets[p].resize(num_inputs); ++ addr_inputs_[p].resize(port_inputs); ++ inv_addr_nets[p].resize(port_inputs); + +- for (int i = 0; i < num_inputs; ++i) { ++ for (int i = 0; i < port_inputs; ++i) { + addr_inputs_[p][i] + = makeBTerm(fmt::format("{}[{}]", port_prefix, i), dbIoType::INPUT); + inv_addr_nets[p][i] +@@ -2013,11 +2063,18 @@ void RamGen::generate(const int mask_size, + vector(num_inputs)); + for (int row = 0; row < num_rows; ++row) { + for (int w = 0; w < column_mux_ratio; ++w) { +- const int word = wordAt(row, w); +- for (int input = 0; input < num_inputs; ++input) { +- decoder_input_nets[p][row * column_mux_ratio + w][input] +- = ((word >> input) & 1) ? addr_inputs_[p][input]->getNet() +- : inv_addr_nets[p][input]; ++ auto& literals = decoder_input_nets[p][row * column_mux_ratio + w]; ++ if (port_bank >= 0 && bankAt(row, w) != port_bank) { ++ literals.clear(); // a word of another bank: no decoder ++ continue; ++ } ++ // a banked read port decodes the word's index in its bank ++ const int word = port_bank >= 0 ? indexInBank(row) : wordAt(row, w); ++ literals.resize(port_inputs); ++ for (int input = 0; input < port_inputs; ++input) { ++ literals[input] = ((word >> input) & 1) ++ ? addr_inputs_[p][input]->getNet() ++ : inv_addr_nets[p][input]; + } + } + } +@@ -2061,10 +2118,21 @@ void RamGen::generate(const int mask_size, + read_select_nets[r_sel_idx++] = makeSelectNets( + fmt::format("r_sel_p{}", p), num_selects, RamPortType::Read); + } ++ // a banked read port selects only its bank's words ++ if (port_bank >= 0) { ++ for (int slot = 0; slot < num_selects; ++slot) { ++ if (decoder_input_nets[p][slot].empty()) { ++ dbNet::destroy(decoder_output_nets[p][slot]); ++ dbNet::destroy(read_select_nets[r_sel_idx - 1][slot]); ++ decoder_output_nets[p][slot] = nullptr; ++ read_select_nets[r_sel_idx - 1][slot] = nullptr; ++ } ++ } ++ } + } + + // start of input/output net creation +- int r_total = rw_ports + r_ports; ++ int r_total = rw_ports + r_ports_all; + q_outputs_.resize(r_total); + // One data bus per write port: D, or with more than one D0, D1, ... + vector> data_inputs(num_write); +@@ -2080,15 +2148,22 @@ void RamGen::generate(const int mask_size, + } + + // if total read ports == 1, only have Q outputs +- if (r_total == 1) { ++ if (r_plain_ == 1) { + auto out_name = fmt::format("Q[{}]", bit); + q_outputs_[0].push_back(makeBTerm(out_name, dbIoType::OUTPUT)); + } else { +- for (int port = 0; port < r_total; ++port) { ++ for (int port = 0; port < r_plain_; ++port) { + auto out_name = fmt::format("Q{}[{}]", port, bit); + q_outputs_[port].push_back(makeBTerm(out_name, dbIoType::OUTPUT)); + } + } ++ // a banked read port's data, one bus per bank ++ for (int port = r_plain_; port < r_total; ++port) { ++ const int kb = port - r_plain_; ++ auto out_name ++ = fmt::format("Qrb{}_b{}[{}]", kb / banks_, kb % banks_, bit); ++ q_outputs_[port].push_back(makeBTerm(out_name, dbIoType::OUTPUT)); ++ } + } + + // Intermediate nets between tristate outputs and Q BTerms +@@ -2188,7 +2263,11 @@ void RamGen::generate(const int mask_size, + if (wordAt(row, w) == zero_word_ && !storage_inverted_) { + continue; + } +- terms.push_back({row, w, select_at(read_select_nets[port], row, w)}); ++ dbNet* select = select_at(read_select_nets[port], row, w); ++ if (select == nullptr) { ++ continue; // a banked read port's other banks ++ } ++ terms.push_back({row, w, select}); + } + } + return terms; +@@ -2250,7 +2329,7 @@ void RamGen::generate(const int mask_size, + mask_size, + row, + rw_ports, +- r_ports, ++ r_ports_all, + w_ports, + word_idx, + column_mux_ratio, +@@ -2764,6 +2843,14 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + for (int i = 0; i < r_ports; i++) { + port_list += fmt::format(",\n addr_r{}", i); + } ++ // banked read ports: an address and a data output per bank ++ const int bank_bits = std::max( ++ 1, static_cast(std::ceil(std::log2(std::max(words_per_bank_, 1))))); ++ for (int k = 0; k < rb_ports_; ++k) { ++ for (int b = 0; b < banks_; ++b) { ++ port_list += fmt::format(",\n addr_rb{}_b{}", k, b); ++ } ++ } + for (int w = 0; w < num_write; ++w) { + port_list += ",\n " + wbus("we", w); + } +@@ -2798,6 +2885,35 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + + // Build read port logic + std::string read_port_logic; ++ for (int k = 0; k < rb_ports_; ++k) { ++ for (int b = 0; b < banks_; ++b) { ++ port_list += fmt::format(",\n Qrb{}_b{}", k, b); ++ output_declaration += fmt::format( ++ " output reg [{}:0] Qrb{}_b{};\n", word_size_bit - 1, k, b); ++ addr_declarations += fmt::format( ++ " input [{}:0] addr_rb{}_b{};\n", bank_bits - 1, k, b); ++ // the word at index addr in bank b ++ const std::string word ++ = bank_interleaved_ ++ ? fmt::format("addr_rb{}_b{} * {} + {}", k, b, banks_, b) ++ : fmt::format("{} + addr_rb{}_b{}", b * words_per_bank_, k, b); ++ const std::string value ++ = zero_word_ >= 0 ? fmt::format("({}) == {} ? {}'d0 : mem[{}]", ++ word, ++ zero_word_, ++ word_size_bit, ++ word) ++ : fmt::format("mem[{}]", word); ++ read_port_logic += fmt::format(R"( always @(*) begin ++ Qrb{}_b{} = {}; ++ end ++ ++)", ++ k, ++ b, ++ value); ++ } ++ } + for (int i = 0; i < r_total; i++) { + std::string port_name = (r_total == 1) ? "Q" : fmt::format("Q{}", i); + std::string addr_name; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index d5eb7723c5..037e28f5ff 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -48,7 +48,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* reset_value, + const int banks, + const int bank_columns, +- const char* bank_order) ++ const char* bank_order, ++ const int rb_ports) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -101,7 +102,7 @@ generate_ram_netlist_cmd(int mask_size, + ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, +- reset_value, banks, bank_columns, bank_order); ++ reset_value, banks, bank_columns, bank_order, rb_ports); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 315a3d88bd..3466fe562c 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -13,11 +13,13 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-banks count] + [-bank_columns count] + [-bank_order contiguous|interleaved] ++ [-rb_ports count] + [-zero_word word] + [-reset_value value] + [-banks count] + [-bank_columns count] + [-bank_order contiguous|interleaved] ++ [-rb_ports count] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -31,7 +33,7 @@ proc generate_ram_netlist { args } { + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order } flags {} ++ -banks -bank_columns -bank_order -rb_ports } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -107,7 +109,7 @@ proc generate_ram_netlist { args } { + utl::error RAM 53 "A read/write port is the only write port." + } + +- if { $rw_ports + $r_ports < 1 } { ++ if { $rw_ports + $r_ports < 1 && ![info exists keys(-rb_ports)] } { + utl::error RAM 36 "Must specify at least one read output port" + } + +@@ -177,6 +179,11 @@ proc generate_ram_netlist { args } { + if { [info exists keys(-bank_columns)] } { + set bank_columns $keys(-bank_columns) + } ++ # Banked read ports: an address and a data output per bank. ++ set rb_ports 0 ++ if { [info exists keys(-rb_ports)] } { ++ set rb_ports $keys(-rb_ports) ++ } + set bank_order contiguous + if { [info exists keys(-bank_order)] } { + set bank_order $keys(-bank_order) +@@ -187,7 +194,8 @@ proc generate_ram_netlist { args } { + + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ +- $read_style $zero_word $reset_value $banks $bank_columns $bank_order ++ $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ ++ $rb_ports + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -222,7 +230,7 @@ proc generate_ram { args } { + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order } flags {} ++ -banks -bank_columns -bank_order -rb_ports } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -271,7 +279,7 @@ proc generate_ram { args } { + lappend ram_netlist_args -reset_value $keys(-reset_value) + } + +- foreach key {-banks -bank_columns -bank_order} { ++ foreach key {-banks -bank_columns -bank_order -rb_ports} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index fdb75124a0..cd2a6d7cdb 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_rb_asap7", + "make_8x8_2r1w_banks_asap7", + "make_8x8_2r1w_reset_asap7", + "make_8x8_2r1w_zero_asap7", +@@ -110,6 +111,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_banks_asap7_behavioral.vok", + ], ++ "make_8x8_rb_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_rb_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_rb_asap7.defok b/src/ram/test/make_8x8_rb_asap7.defok +new file mode 100644 +index 0000000000..01335280e1 +--- /dev/null ++++ b/src/ram/test/make_8x8_rb_asap7.defok +@@ -0,0 +1,613 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 3639 135 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 674 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 674 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 674 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 674 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 674 BY 1 STEP 5 0 ; ++COMPONENTS 240 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 1382 108 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1728 108 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 2073 108 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 2419 108 ) N ; ++ - decoder_p0.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3067 0 ) N ; ++ - decoder_p0.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3132 0 ) N ; ++ - decoder_p0.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3067 27 ) FS ; ++ - decoder_p0.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3132 27 ) FS ; ++ - decoder_p0.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3067 54 ) N ; ++ - decoder_p0.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3132 54 ) N ; ++ - decoder_p0.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3067 81 ) FS ; ++ - decoder_p0.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3132 81 ) FS ; ++ - decoder_p0.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3099 0 ) N ; ++ - decoder_p0.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3164 0 ) N ; ++ - decoder_p0.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3099 27 ) FS ; ++ - decoder_p0.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3164 27 ) FS ; ++ - decoder_p0.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3099 54 ) N ; ++ - decoder_p0.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3164 54 ) N ; ++ - decoder_p0.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3099 81 ) FS ; ++ - decoder_p0.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3164 81 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 3542 54 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 3542 27 ) FS ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 3542 0 ) N ; ++ - decoder_p1.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3240 0 ) N ; ++ - decoder_p1.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3304 0 ) N ; ++ - decoder_p1.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3240 27 ) FS ; ++ - decoder_p1.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3304 27 ) FS ; ++ - decoder_p1.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3240 54 ) N ; ++ - decoder_p1.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3304 54 ) N ; ++ - decoder_p1.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3240 81 ) FS ; ++ - decoder_p1.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3304 81 ) FS ; ++ - decoder_p1.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3272 0 ) N ; ++ - decoder_p1.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3337 0 ) N ; ++ - decoder_p1.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3272 27 ) FS ; ++ - decoder_p1.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3337 27 ) FS ; ++ - decoder_p1.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3272 54 ) N ; ++ - decoder_p1.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3337 54 ) N ; ++ - decoder_p1.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3272 81 ) FS ; ++ - decoder_p1.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3337 81 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 3558 54 ) N ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 3558 27 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 3558 0 ) N ; ++ - decoder_p2.buf_word0 HB1xp67_ASAP7_75t_R + PLACED ( 3391 0 ) N ; ++ - decoder_p2.buf_word2 HB1xp67_ASAP7_75t_R + PLACED ( 3391 27 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 3574 54 ) N ; ++ - decoder_p3.buf_word1 HB1xp67_ASAP7_75t_R + PLACED ( 3434 0 ) N ; ++ - decoder_p3.buf_word3 HB1xp67_ASAP7_75t_R + PLACED ( 3434 27 ) FS ; ++ - decoder_p3.inv_p3_a0 INVx1_ASAP7_75t_R + PLACED ( 3591 54 ) N ; ++ - decoder_p4.buf_word4 HB1xp67_ASAP7_75t_R + PLACED ( 3477 54 ) N ; ++ - decoder_p4.buf_word6 HB1xp67_ASAP7_75t_R + PLACED ( 3477 81 ) FS ; ++ - decoder_p4.inv_p4_a0 INVx1_ASAP7_75t_R + PLACED ( 3607 54 ) N ; ++ - decoder_p5.buf_word5 HB1xp67_ASAP7_75t_R + PLACED ( 3520 54 ) N ; ++ - decoder_p5.buf_word7 HB1xp67_ASAP7_75t_R + PLACED ( 3520 81 ) FS ; ++ - decoder_p5.inv_p5_a0 INVx1_ASAP7_75t_R + PLACED ( 3623 54 ) N ; ++ - read_p0_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - read_p0_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 280 0 ) N ; ++ - read_p0_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_p0_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_p0_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - read_p0_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 626 0 ) N ; ++ - read_p0_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_p0_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_p0_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - read_p0_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 972 0 ) N ; ++ - read_p0_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_p0_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_p0_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - read_p0_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 0 ) N ; ++ - read_p0_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_p0_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_p0_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1382 0 ) N ; ++ - read_p0_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1663 0 ) N ; ++ - read_p0_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1490 54 ) N ; ++ - read_p0_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1663 54 ) N ; ++ - read_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1490 27 ) FS ; ++ - read_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1663 27 ) FS ; ++ - read_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1490 81 ) FS ; ++ - read_p0_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1728 0 ) N ; ++ - read_p0_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2008 0 ) N ; ++ - read_p0_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 54 ) N ; ++ - read_p0_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2008 54 ) N ; ++ - read_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1836 27 ) FS ; ++ - read_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2008 27 ) FS ; ++ - read_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1836 81 ) FS ; ++ - read_p0_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2073 0 ) N ; ++ - read_p0_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2354 0 ) N ; ++ - read_p0_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2181 54 ) N ; ++ - read_p0_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2354 54 ) N ; ++ - read_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2181 27 ) FS ; ++ - read_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2354 27 ) FS ; ++ - read_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2181 81 ) FS ; ++ - read_p0_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2419 0 ) N ; ++ - read_p0_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2700 0 ) N ; ++ - read_p0_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2527 54 ) N ; ++ - read_p0_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2700 54 ) N ; ++ - read_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2527 27 ) FS ; ++ - read_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2700 27 ) FS ; ++ - read_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2527 81 ) FS ; ++ - read_p1_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 32 0 ) N ; ++ - read_p1_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 378 0 ) N ; ++ - read_p1_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 723 0 ) N ; ++ - read_p1_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1069 0 ) N ; ++ - read_p1_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1414 0 ) N ; ++ - read_p1_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1760 0 ) N ; ++ - read_p1_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2106 0 ) N ; ++ - read_p1_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2451 0 ) N ; ++ - read_p2_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 313 0 ) N ; ++ - read_p2_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 658 0 ) N ; ++ - read_p2_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 0 ) N ; ++ - read_p2_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 0 ) N ; ++ - read_p2_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1695 0 ) N ; ++ - read_p2_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2041 0 ) N ; ++ - read_p2_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2386 0 ) N ; ++ - read_p2_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2732 0 ) N ; ++ - read_p3_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_p3_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_p3_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_p3_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_p3_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1522 54 ) N ; ++ - read_p3_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 54 ) N ; ++ - read_p3_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2214 54 ) N ; ++ - read_p3_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2559 54 ) N ; ++ - read_p4_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_p4_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_p4_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_p4_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_p4_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1695 54 ) N ; ++ - read_p4_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2041 54 ) N ; ++ - read_p4_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2386 54 ) N ; ++ - read_p4_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2732 54 ) N ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3196 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3218 0 ) N ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3196 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3218 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3196 54 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3218 54 ) N ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3196 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3218 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3369 0 ) N ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3369 27 ) FS ; ++ - sel_buf_r_p3.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3412 0 ) N ; ++ - sel_buf_r_p3.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3412 27 ) FS ; ++ - sel_buf_r_p4.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3456 54 ) N ; ++ - sel_buf_r_p4.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3456 81 ) FS ; ++ - sel_buf_r_p5.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3499 54 ) N ; ++ - sel_buf_r_p5.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3499 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3024 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3045 0 ) N ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3024 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3045 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3024 54 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3045 54 ) N ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3024 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3045 81 ) FS ; ++ - storage_0_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - storage_0_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - storage_0_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - storage_0_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - storage_0_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 0 ) N ; ++ - storage_0_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 0 ) N ; ++ - storage_0_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 0 ) N ; ++ - storage_0_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 0 ) N ; ++ - storage_0_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 0 ) N ; ++ - storage_0_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 27 ) FS ; ++ - storage_1_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 27 ) FS ; ++ - storage_1_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 27 ) FS ; ++ - storage_1_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 27 ) FS ; ++ - storage_1_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 27 ) FS ; ++ - storage_1_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 27 ) FS ; ++ - storage_1_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 54 ) N ; ++ - storage_2_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 54 ) N ; ++ - storage_2_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 54 ) N ; ++ - storage_2_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 54 ) N ; ++ - storage_2_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 54 ) N ; ++ - storage_2_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 54 ) N ; ++ - storage_2_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 81 ) FS ; ++ - storage_3_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 81 ) FS ; ++ - storage_3_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 81 ) FS ; ++ - storage_3_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 81 ) FS ; ++ - storage_3_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 81 ) FS ; ++ - storage_3_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 81 ) FS ; ++ - storage_3_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 81 ) FS ; ++END COMPONENTS ++PINS 60 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q[0] + NET Q[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[1] + NET Q[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[2] + NET Q[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[3] + NET Q[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[4] + NET Q[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[5] + NET Q[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[6] + NET Q[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[7] + NET Q[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[0] + NET Qrb0_b0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[1] + NET Qrb0_b0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[2] + NET Qrb0_b0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[3] + NET Qrb0_b0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[4] + NET Qrb0_b0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[5] + NET Qrb0_b0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[6] + NET Qrb0_b0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[7] + NET Qrb0_b0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[0] + NET Qrb0_b1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[1] + NET Qrb0_b1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[2] + NET Qrb0_b1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[3] + NET Qrb0_b1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[4] + NET Qrb0_b1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[5] + NET Qrb0_b1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[6] + NET Qrb0_b1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[7] + NET Qrb0_b1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[0] + NET Qrb0_b2[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[1] + NET Qrb0_b2[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[2] + NET Qrb0_b2[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[3] + NET Qrb0_b2[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[4] + NET Qrb0_b2[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[5] + NET Qrb0_b2[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[6] + NET Qrb0_b2[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[7] + NET Qrb0_b2[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[0] + NET Qrb0_b3[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[1] + NET Qrb0_b3[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[2] + NET Qrb0_b3[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[3] + NET Qrb0_b3[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[4] + NET Qrb0_b3[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[5] + NET Qrb0_b3[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[6] + NET Qrb0_b3[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[7] + NET Qrb0_b3[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b0[0] + NET addr_rb0_b0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b1[0] + NET addr_rb0_b1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b2[0] + NET addr_rb0_b2[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b3[0] + NET addr_rb0_b3[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 260 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_3_1_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_1_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ( storage_1_1_0.bit0.bit D ) ( storage_1_0_0.bit0.bit D ) ++ ( storage_0_1_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_3_1_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_1_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ( storage_1_1_0.bit1.bit D ) ( storage_1_0_0.bit1.bit D ) ++ ( storage_0_1_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_3_1_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_1_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ( storage_1_1_0.bit2.bit D ) ( storage_1_0_0.bit2.bit D ) ++ ( storage_0_1_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_3_1_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_1_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ( storage_1_1_0.bit3.bit D ) ( storage_1_0_0.bit3.bit D ) ++ ( storage_0_1_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_3_1_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_1_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ( storage_1_1_0.bit4.bit D ) ( storage_1_0_0.bit4.bit D ) ++ ( storage_0_1_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_3_1_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_1_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ( storage_1_1_0.bit5.bit D ) ( storage_1_0_0.bit5.bit D ) ++ ( storage_0_1_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_3_1_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_1_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ( storage_1_1_0.bit6.bit D ) ( storage_1_0_0.bit6.bit D ) ++ ( storage_0_1_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_3_1_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_1_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ( storage_1_1_0.bit7.bit D ) ( storage_1_0_0.bit7.bit D ) ++ ( storage_0_1_0.bit7.bit D ) + USE SIGNAL ; ++ - Q[0] ( PIN Q[0] ) ( read_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[1] ( PIN Q[1] ) ( read_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[2] ( PIN Q[2] ) ( read_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[3] ( PIN Q[3] ) ( read_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[4] ( PIN Q[4] ) ( read_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[5] ( PIN Q[5] ) ( read_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[6] ( PIN Q[6] ) ( read_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[7] ( PIN Q[7] ) ( read_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Qrb0_b0[0] ( PIN Qrb0_b0[0] ) ( read_p1_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[1] ( PIN Qrb0_b0[1] ) ( read_p1_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[2] ( PIN Qrb0_b0[2] ) ( read_p1_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[3] ( PIN Qrb0_b0[3] ) ( read_p1_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[4] ( PIN Qrb0_b0[4] ) ( read_p1_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[5] ( PIN Qrb0_b0[5] ) ( read_p1_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[6] ( PIN Qrb0_b0[6] ) ( read_p1_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[7] ( PIN Qrb0_b0[7] ) ( read_p1_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b1[0] ( PIN Qrb0_b1[0] ) ( read_p2_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[1] ( PIN Qrb0_b1[1] ) ( read_p2_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[2] ( PIN Qrb0_b1[2] ) ( read_p2_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[3] ( PIN Qrb0_b1[3] ) ( read_p2_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[4] ( PIN Qrb0_b1[4] ) ( read_p2_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[5] ( PIN Qrb0_b1[5] ) ( read_p2_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[6] ( PIN Qrb0_b1[6] ) ( read_p2_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[7] ( PIN Qrb0_b1[7] ) ( read_p2_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b2[0] ( PIN Qrb0_b2[0] ) ( read_p3_b0.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[1] ( PIN Qrb0_b2[1] ) ( read_p3_b1.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[2] ( PIN Qrb0_b2[2] ) ( read_p3_b2.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[3] ( PIN Qrb0_b2[3] ) ( read_p3_b3.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[4] ( PIN Qrb0_b2[4] ) ( read_p3_b4.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[5] ( PIN Qrb0_b2[5] ) ( read_p3_b5.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[6] ( PIN Qrb0_b2[6] ) ( read_p3_b6.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[7] ( PIN Qrb0_b2[7] ) ( read_p3_b7.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b3[0] ( PIN Qrb0_b3[0] ) ( read_p4_b0.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[1] ( PIN Qrb0_b3[1] ) ( read_p4_b1.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[2] ( PIN Qrb0_b3[2] ) ( read_p4_b2.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[3] ( PIN Qrb0_b3[3] ) ( read_p4_b3.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[4] ( PIN Qrb0_b3[4] ) ( read_p4_b4.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[5] ( PIN Qrb0_b3[5] ) ( read_p4_b5.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[6] ( PIN Qrb0_b3[6] ) ( read_p4_b6.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[7] ( PIN Qrb0_b3[7] ) ( read_p4_b7.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and0_word5 A ) ( decoder_p1.and0_word4 A ) ( decoder_p1.and0_word1 A ) ( decoder_p1.and0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and0_word6 B ) ( decoder_p1.and0_word4 B ) ( decoder_p1.and0_word2 B ) ( decoder_p1.and0_word0 B ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and1_word3 B ) ( decoder_p1.and1_word2 B ) ( decoder_p1.and1_word1 B ) ( decoder_p1.and1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and0_word7 A ) ( decoder_p1.and0_word6 A ) ( decoder_p1.and0_word3 A ) ( decoder_p1.and0_word2 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and0_word7 B ) ( decoder_p1.and0_word5 B ) ( decoder_p1.and0_word3 B ) ( decoder_p1.and0_word1 B ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and1_word7 B ) ( decoder_p1.and1_word6 B ) ( decoder_p1.and1_word5 B ) ( decoder_p1.and1_word4 B ) + USE SIGNAL ; ++ - addr_rb0_b0.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.buf_word0 A ) + USE SIGNAL ; ++ - addr_rb0_b0[0] ( PIN addr_rb0_b0[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.buf_word2 A ) + USE SIGNAL ; ++ - addr_rb0_b1.inv_addr[0] ( decoder_p3.inv_p3_a0 Y ) ( decoder_p3.buf_word1 A ) + USE SIGNAL ; ++ - addr_rb0_b1[0] ( PIN addr_rb0_b1[0] ) ( decoder_p3.inv_p3_a0 A ) ( decoder_p3.buf_word3 A ) + USE SIGNAL ; ++ - addr_rb0_b2.inv_addr[0] ( decoder_p4.inv_p4_a0 Y ) ( decoder_p4.buf_word4 A ) + USE SIGNAL ; ++ - addr_rb0_b2[0] ( PIN addr_rb0_b2[0] ) ( decoder_p4.inv_p4_a0 A ) ( decoder_p4.buf_word6 A ) + USE SIGNAL ; ++ - addr_rb0_b3.inv_addr[0] ( decoder_p5.inv_p5_a0 Y ) ( decoder_p5.buf_word5 A ) + USE SIGNAL ; ++ - addr_rb0_b3[0] ( PIN addr_rb0_b3[0] ) ( decoder_p5.inv_p5_a0 A ) ( decoder_p5.buf_word7 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and0_word5 A ) ( decoder_p0.and0_word4 A ) ( decoder_p0.and0_word1 A ) ( decoder_p0.and0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and0_word6 B ) ( decoder_p0.and0_word4 B ) ( decoder_p0.and0_word2 B ) ( decoder_p0.and0_word0 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and1_word3 B ) ( decoder_p0.and1_word2 B ) ( decoder_p0.and1_word1 B ) ( decoder_p0.and1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and0_word7 A ) ( decoder_p0.and0_word6 A ) ( decoder_p0.and0_word3 A ) ( decoder_p0.and0_word2 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and0_word7 B ) ( decoder_p0.and0_word5 B ) ( decoder_p0.and0_word3 B ) ( decoder_p0.and0_word1 B ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and1_word7 B ) ( decoder_p0.and1_word6 B ) ( decoder_p0.and1_word5 B ) ( decoder_p0.and1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_3_1_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_1_0.cg CLK ) ( storage_2_0_0.cg CLK ) ( storage_1_1_0.cg CLK ) ( storage_1_0_0.cg CLK ) ++ ( storage_0_1_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and1_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and1_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and1_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and1_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and1_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and1_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and1_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and1_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p0.y0_word0 ( decoder_p0.and1_word0 A ) ( decoder_p0.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word1 ( decoder_p0.and1_word1 A ) ( decoder_p0.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word2 ( decoder_p0.and1_word2 A ) ( decoder_p0.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word3 ( decoder_p0.and1_word3 A ) ( decoder_p0.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word4 ( decoder_p0.and1_word4 A ) ( decoder_p0.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word5 ( decoder_p0.and1_word5 A ) ( decoder_p0.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word6 ( decoder_p0.and1_word6 A ) ( decoder_p0.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word7 ( decoder_p0.and1_word7 A ) ( decoder_p0.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and1_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and1_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and1_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and1_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and1_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and1_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and1_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and1_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.y0_word0 ( decoder_p1.and1_word0 A ) ( decoder_p1.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word1 ( decoder_p1.and1_word1 A ) ( decoder_p1.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word2 ( decoder_p1.and1_word2 A ) ( decoder_p1.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word3 ( decoder_p1.and1_word3 A ) ( decoder_p1.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word4 ( decoder_p1.and1_word4 A ) ( decoder_p1.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word5 ( decoder_p1.and1_word5 A ) ( decoder_p1.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word6 ( decoder_p1.and1_word6 A ) ( decoder_p1.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word7 ( decoder_p1.and1_word7 A ) ( decoder_p1.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.buf_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.buf_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p3.word1 ( decoder_p3.buf_word1 Y ) ( sel_buf_r_p3.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p3.word3 ( decoder_p3.buf_word3 Y ) ( sel_buf_r_p3.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p4.word4 ( decoder_p4.buf_word4 Y ) ( sel_buf_r_p4.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p4.word6 ( decoder_p4.buf_word6 Y ) ( sel_buf_r_p4.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p5.word5 ( decoder_p5.buf_word5 Y ) ( sel_buf_r_p5.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p5.word7 ( decoder_p5.buf_word7 Y ) ( sel_buf_r_p5.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_p0_b7.aoi_r0_w0 A2 ) ( read_p0_b7.aoi_r0_w0 A1 ) ( read_p0_b6.aoi_r0_w0 A2 ) ( read_p0_b6.aoi_r0_w0 A1 ) ( read_p0_b5.aoi_r0_w0 A2 ) ( read_p0_b5.aoi_r0_w0 A1 ) ++ ( read_p0_b4.aoi_r0_w0 A2 ) ( read_p0_b4.aoi_r0_w0 A1 ) ( read_p0_b3.aoi_r0_w0 A2 ) ( read_p0_b3.aoi_r0_w0 A1 ) ( read_p0_b2.aoi_r0_w0 A2 ) ( read_p0_b2.aoi_r0_w0 A1 ) ( read_p0_b1.aoi_r0_w0 A2 ) ( read_p0_b1.aoi_r0_w0 A1 ) ++ ( read_p0_b0.aoi_r0_w0 A2 ) ( read_p0_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_p0_b7.aoi_r0_w1 A1 ) ( read_p0_b6.aoi_r0_w1 A1 ) ( read_p0_b5.aoi_r0_w1 A1 ) ( read_p0_b4.aoi_r0_w1 A1 ) ( read_p0_b3.aoi_r0_w1 A1 ) ( read_p0_b2.aoi_r0_w1 A1 ) ++ ( read_p0_b1.aoi_r0_w1 A1 ) ( read_p0_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_p0_b7.aoi_r0_w0 B1 ) ( read_p0_b6.aoi_r0_w0 B1 ) ( read_p0_b5.aoi_r0_w0 B1 ) ( read_p0_b4.aoi_r0_w0 B1 ) ( read_p0_b3.aoi_r0_w0 B1 ) ( read_p0_b2.aoi_r0_w0 B1 ) ++ ( read_p0_b1.aoi_r0_w0 B1 ) ( read_p0_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_p0_b7.aoi_r0_w1 B1 ) ( read_p0_b6.aoi_r0_w1 B1 ) ( read_p0_b5.aoi_r0_w1 B1 ) ( read_p0_b4.aoi_r0_w1 B1 ) ( read_p0_b3.aoi_r0_w1 B1 ) ( read_p0_b2.aoi_r0_w1 B1 ) ++ ( read_p0_b1.aoi_r0_w1 B1 ) ( read_p0_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_p0_b7.aoi_r2_w0 A1 ) ( read_p0_b6.aoi_r2_w0 A1 ) ( read_p0_b5.aoi_r2_w0 A1 ) ( read_p0_b4.aoi_r2_w0 A1 ) ( read_p0_b3.aoi_r2_w0 A1 ) ( read_p0_b2.aoi_r2_w0 A1 ) ++ ( read_p0_b1.aoi_r2_w0 A1 ) ( read_p0_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_p0_b7.aoi_r2_w1 A1 ) ( read_p0_b6.aoi_r2_w1 A1 ) ( read_p0_b5.aoi_r2_w1 A1 ) ( read_p0_b4.aoi_r2_w1 A1 ) ( read_p0_b3.aoi_r2_w1 A1 ) ( read_p0_b2.aoi_r2_w1 A1 ) ++ ( read_p0_b1.aoi_r2_w1 A1 ) ( read_p0_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_p0_b7.aoi_r2_w0 B1 ) ( read_p0_b6.aoi_r2_w0 B1 ) ( read_p0_b5.aoi_r2_w0 B1 ) ( read_p0_b4.aoi_r2_w0 B1 ) ( read_p0_b3.aoi_r2_w0 B1 ) ( read_p0_b2.aoi_r2_w0 B1 ) ++ ( read_p0_b1.aoi_r2_w0 B1 ) ( read_p0_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_p0_b7.aoi_r2_w1 B1 ) ( read_p0_b6.aoi_r2_w1 B1 ) ( read_p0_b5.aoi_r2_w1 B1 ) ( read_p0_b4.aoi_r2_w1 B1 ) ( read_p0_b3.aoi_r2_w1 B1 ) ( read_p0_b2.aoi_r2_w1 B1 ) ++ ( read_p0_b1.aoi_r2_w1 B1 ) ( read_p0_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_p1_b7.aoi_r0_w0 A2 ) ( read_p1_b7.aoi_r0_w0 A1 ) ( read_p1_b6.aoi_r0_w0 A2 ) ( read_p1_b6.aoi_r0_w0 A1 ) ( read_p1_b5.aoi_r0_w0 A2 ) ( read_p1_b5.aoi_r0_w0 A1 ) ++ ( read_p1_b4.aoi_r0_w0 A2 ) ( read_p1_b4.aoi_r0_w0 A1 ) ( read_p1_b3.aoi_r0_w0 A2 ) ( read_p1_b3.aoi_r0_w0 A1 ) ( read_p1_b2.aoi_r0_w0 A2 ) ( read_p1_b2.aoi_r0_w0 A1 ) ( read_p1_b1.aoi_r0_w0 A2 ) ( read_p1_b1.aoi_r0_w0 A1 ) ++ ( read_p1_b0.aoi_r0_w0 A2 ) ( read_p1_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_p1_b7.aoi_r0_w0 B1 ) ( read_p1_b6.aoi_r0_w0 B1 ) ( read_p1_b5.aoi_r0_w0 B1 ) ( read_p1_b4.aoi_r0_w0 B1 ) ( read_p1_b3.aoi_r0_w0 B1 ) ( read_p1_b2.aoi_r0_w0 B1 ) ++ ( read_p1_b1.aoi_r0_w0 B1 ) ( read_p1_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r1 ( sel_buf_r_p3.sel_buf_1 Y ) ( read_p2_b7.aoi_r0_w1 A1 ) ( read_p2_b6.aoi_r0_w1 A1 ) ( read_p2_b5.aoi_r0_w1 A1 ) ( read_p2_b4.aoi_r0_w1 A1 ) ( read_p2_b3.aoi_r0_w1 A1 ) ( read_p2_b2.aoi_r0_w1 A1 ) ++ ( read_p2_b1.aoi_r0_w1 A1 ) ( read_p2_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r3 ( sel_buf_r_p3.sel_buf_3 Y ) ( read_p2_b7.aoi_r0_w1 B1 ) ( read_p2_b6.aoi_r0_w1 B1 ) ( read_p2_b5.aoi_r0_w1 B1 ) ( read_p2_b4.aoi_r0_w1 B1 ) ( read_p2_b3.aoi_r0_w1 B1 ) ( read_p2_b2.aoi_r0_w1 B1 ) ++ ( read_p2_b1.aoi_r0_w1 B1 ) ( read_p2_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p4.select_r4 ( sel_buf_r_p4.sel_buf_4 Y ) ( read_p3_b7.aoi_r2_w0 A1 ) ( read_p3_b6.aoi_r2_w0 A1 ) ( read_p3_b5.aoi_r2_w0 A1 ) ( read_p3_b4.aoi_r2_w0 A1 ) ( read_p3_b3.aoi_r2_w0 A1 ) ( read_p3_b2.aoi_r2_w0 A1 ) ++ ( read_p3_b1.aoi_r2_w0 A1 ) ( read_p3_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p4.select_r6 ( sel_buf_r_p4.sel_buf_6 Y ) ( read_p3_b7.aoi_r2_w0 B1 ) ( read_p3_b6.aoi_r2_w0 B1 ) ( read_p3_b5.aoi_r2_w0 B1 ) ( read_p3_b4.aoi_r2_w0 B1 ) ( read_p3_b3.aoi_r2_w0 B1 ) ( read_p3_b2.aoi_r2_w0 B1 ) ++ ( read_p3_b1.aoi_r2_w0 B1 ) ( read_p3_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p5.select_r5 ( sel_buf_r_p5.sel_buf_5 Y ) ( read_p4_b7.aoi_r2_w1 A1 ) ( read_p4_b6.aoi_r2_w1 A1 ) ( read_p4_b5.aoi_r2_w1 A1 ) ( read_p4_b4.aoi_r2_w1 A1 ) ( read_p4_b3.aoi_r2_w1 A1 ) ( read_p4_b2.aoi_r2_w1 A1 ) ++ ( read_p4_b1.aoi_r2_w1 A1 ) ( read_p4_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p5.select_r7 ( sel_buf_r_p5.sel_buf_7 Y ) ( read_p4_b7.aoi_r2_w1 B1 ) ( read_p4_b6.aoi_r2_w1 B1 ) ( read_p4_b5.aoi_r2_w1 B1 ) ( read_p4_b4.aoi_r2_w1 B1 ) ( read_p4_b3.aoi_r2_w1 B1 ) ( read_p4_b2.aoi_r2_w1 B1 ) ++ ( read_p4_b1.aoi_r2_w1 B1 ) ( read_p4_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - read_p0_b0.t0_2 ( read_p0_b0.nand_r0_4 A ) ( read_p0_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b0.t0_4 ( read_p0_b0.nor_r0_8 A ) ( read_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b0.t2_4 ( read_p0_b0.aoi_r2_w0 Y ) ( read_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b0.t4_6 ( read_p0_b0.nand_r4_8 A ) ( read_p0_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b0.t4_8 ( read_p0_b0.nor_r0_8 B ) ( read_p0_b0.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b0.t6_8 ( read_p0_b0.aoi_r2_w1 Y ) ( read_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b1.t0_2 ( read_p0_b1.nand_r0_4 A ) ( read_p0_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b1.t0_4 ( read_p0_b1.nor_r0_8 A ) ( read_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b1.t2_4 ( read_p0_b1.aoi_r2_w0 Y ) ( read_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b1.t4_6 ( read_p0_b1.nand_r4_8 A ) ( read_p0_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b1.t4_8 ( read_p0_b1.nor_r0_8 B ) ( read_p0_b1.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b1.t6_8 ( read_p0_b1.aoi_r2_w1 Y ) ( read_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b2.t0_2 ( read_p0_b2.nand_r0_4 A ) ( read_p0_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b2.t0_4 ( read_p0_b2.nor_r0_8 A ) ( read_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b2.t2_4 ( read_p0_b2.aoi_r2_w0 Y ) ( read_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b2.t4_6 ( read_p0_b2.nand_r4_8 A ) ( read_p0_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b2.t4_8 ( read_p0_b2.nor_r0_8 B ) ( read_p0_b2.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b2.t6_8 ( read_p0_b2.aoi_r2_w1 Y ) ( read_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b3.t0_2 ( read_p0_b3.nand_r0_4 A ) ( read_p0_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b3.t0_4 ( read_p0_b3.nor_r0_8 A ) ( read_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b3.t2_4 ( read_p0_b3.aoi_r2_w0 Y ) ( read_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b3.t4_6 ( read_p0_b3.nand_r4_8 A ) ( read_p0_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b3.t4_8 ( read_p0_b3.nor_r0_8 B ) ( read_p0_b3.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b3.t6_8 ( read_p0_b3.aoi_r2_w1 Y ) ( read_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b4.t0_2 ( read_p0_b4.nand_r0_4 A ) ( read_p0_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b4.t0_4 ( read_p0_b4.nor_r0_8 A ) ( read_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b4.t2_4 ( read_p0_b4.aoi_r2_w0 Y ) ( read_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b4.t4_6 ( read_p0_b4.nand_r4_8 A ) ( read_p0_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b4.t4_8 ( read_p0_b4.nor_r0_8 B ) ( read_p0_b4.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b4.t6_8 ( read_p0_b4.aoi_r2_w1 Y ) ( read_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b5.t0_2 ( read_p0_b5.nand_r0_4 A ) ( read_p0_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b5.t0_4 ( read_p0_b5.nor_r0_8 A ) ( read_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b5.t2_4 ( read_p0_b5.aoi_r2_w0 Y ) ( read_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b5.t4_6 ( read_p0_b5.nand_r4_8 A ) ( read_p0_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b5.t4_8 ( read_p0_b5.nor_r0_8 B ) ( read_p0_b5.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b5.t6_8 ( read_p0_b5.aoi_r2_w1 Y ) ( read_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b6.t0_2 ( read_p0_b6.nand_r0_4 A ) ( read_p0_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b6.t0_4 ( read_p0_b6.nor_r0_8 A ) ( read_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b6.t2_4 ( read_p0_b6.aoi_r2_w0 Y ) ( read_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b6.t4_6 ( read_p0_b6.nand_r4_8 A ) ( read_p0_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b6.t4_8 ( read_p0_b6.nor_r0_8 B ) ( read_p0_b6.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b6.t6_8 ( read_p0_b6.aoi_r2_w1 Y ) ( read_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b7.t0_2 ( read_p0_b7.nand_r0_4 A ) ( read_p0_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b7.t0_4 ( read_p0_b7.nor_r0_8 A ) ( read_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b7.t2_4 ( read_p0_b7.aoi_r2_w0 Y ) ( read_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b7.t4_6 ( read_p0_b7.nand_r4_8 A ) ( read_p0_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b7.t4_8 ( read_p0_b7.nor_r0_8 B ) ( read_p0_b7.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b7.t6_8 ( read_p0_b7.aoi_r2_w1 Y ) ( read_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_1_0.bit0.storage ( read_p2_b0.aoi_r0_w1 A2 ) ( read_p0_b0.aoi_r0_w1 A2 ) ( storage_0_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit1.storage ( read_p2_b1.aoi_r0_w1 A2 ) ( read_p0_b1.aoi_r0_w1 A2 ) ( storage_0_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit2.storage ( read_p2_b2.aoi_r0_w1 A2 ) ( read_p0_b2.aoi_r0_w1 A2 ) ( storage_0_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit3.storage ( read_p2_b3.aoi_r0_w1 A2 ) ( read_p0_b3.aoi_r0_w1 A2 ) ( storage_0_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit4.storage ( read_p2_b4.aoi_r0_w1 A2 ) ( read_p0_b4.aoi_r0_w1 A2 ) ( storage_0_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit5.storage ( read_p2_b5.aoi_r0_w1 A2 ) ( read_p0_b5.aoi_r0_w1 A2 ) ( storage_0_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit6.storage ( read_p2_b6.aoi_r0_w1 A2 ) ( read_p0_b6.aoi_r0_w1 A2 ) ( storage_0_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit7.storage ( read_p2_b7.aoi_r0_w1 A2 ) ( read_p0_b7.aoi_r0_w1 A2 ) ( storage_0_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.gclock ( storage_0_1_0.cg GCLK ) ( storage_0_1_0.bit7.bit CLK ) ( storage_0_1_0.bit6.bit CLK ) ( storage_0_1_0.bit5.bit CLK ) ( storage_0_1_0.bit4.bit CLK ) ( storage_0_1_0.bit3.bit CLK ) ( storage_0_1_0.bit2.bit CLK ) ++ ( storage_0_1_0.bit1.bit CLK ) ( storage_0_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_1_0.we ( storage_0_1_0.gcand Y ) ( storage_0_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_p1_b0.aoi_r0_w0 B2 ) ( read_p0_b0.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_p1_b1.aoi_r0_w0 B2 ) ( read_p0_b1.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_p1_b2.aoi_r0_w0 B2 ) ( read_p0_b2.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_p1_b3.aoi_r0_w0 B2 ) ( read_p0_b3.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_p1_b4.aoi_r0_w0 B2 ) ( read_p0_b4.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_p1_b5.aoi_r0_w0 B2 ) ( read_p0_b5.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_p1_b6.aoi_r0_w0 B2 ) ( read_p0_b6.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_p1_b7.aoi_r0_w0 B2 ) ( read_p0_b7.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_1_0.bit0.storage ( storage_1_1_0.bit0.bit QN ) ( read_p2_b0.aoi_r0_w1 B2 ) ( read_p0_b0.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit1.storage ( storage_1_1_0.bit1.bit QN ) ( read_p2_b1.aoi_r0_w1 B2 ) ( read_p0_b1.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit2.storage ( storage_1_1_0.bit2.bit QN ) ( read_p2_b2.aoi_r0_w1 B2 ) ( read_p0_b2.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit3.storage ( storage_1_1_0.bit3.bit QN ) ( read_p2_b3.aoi_r0_w1 B2 ) ( read_p0_b3.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit4.storage ( storage_1_1_0.bit4.bit QN ) ( read_p2_b4.aoi_r0_w1 B2 ) ( read_p0_b4.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit5.storage ( storage_1_1_0.bit5.bit QN ) ( read_p2_b5.aoi_r0_w1 B2 ) ( read_p0_b5.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit6.storage ( storage_1_1_0.bit6.bit QN ) ( read_p2_b6.aoi_r0_w1 B2 ) ( read_p0_b6.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit7.storage ( storage_1_1_0.bit7.bit QN ) ( read_p2_b7.aoi_r0_w1 B2 ) ( read_p0_b7.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.gclock ( storage_1_1_0.cg GCLK ) ( storage_1_1_0.bit7.bit CLK ) ( storage_1_1_0.bit6.bit CLK ) ( storage_1_1_0.bit5.bit CLK ) ( storage_1_1_0.bit4.bit CLK ) ( storage_1_1_0.bit3.bit CLK ) ( storage_1_1_0.bit2.bit CLK ) ++ ( storage_1_1_0.bit1.bit CLK ) ( storage_1_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_1_0.we ( storage_1_1_0.gcand Y ) ( storage_1_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_p3_b0.aoi_r2_w0 A2 ) ( read_p0_b0.aoi_r2_w0 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_p3_b1.aoi_r2_w0 A2 ) ( read_p0_b1.aoi_r2_w0 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_p3_b2.aoi_r2_w0 A2 ) ( read_p0_b2.aoi_r2_w0 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_p3_b3.aoi_r2_w0 A2 ) ( read_p0_b3.aoi_r2_w0 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_p3_b4.aoi_r2_w0 A2 ) ( read_p0_b4.aoi_r2_w0 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_p3_b5.aoi_r2_w0 A2 ) ( read_p0_b5.aoi_r2_w0 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_p3_b6.aoi_r2_w0 A2 ) ( read_p0_b6.aoi_r2_w0 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_p3_b7.aoi_r2_w0 A2 ) ( read_p0_b7.aoi_r2_w0 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_1_0.bit0.storage ( read_p4_b0.aoi_r2_w1 A2 ) ( read_p0_b0.aoi_r2_w1 A2 ) ( storage_2_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit1.storage ( read_p4_b1.aoi_r2_w1 A2 ) ( read_p0_b1.aoi_r2_w1 A2 ) ( storage_2_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit2.storage ( read_p4_b2.aoi_r2_w1 A2 ) ( read_p0_b2.aoi_r2_w1 A2 ) ( storage_2_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit3.storage ( read_p4_b3.aoi_r2_w1 A2 ) ( read_p0_b3.aoi_r2_w1 A2 ) ( storage_2_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit4.storage ( read_p4_b4.aoi_r2_w1 A2 ) ( read_p0_b4.aoi_r2_w1 A2 ) ( storage_2_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit5.storage ( read_p4_b5.aoi_r2_w1 A2 ) ( read_p0_b5.aoi_r2_w1 A2 ) ( storage_2_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit6.storage ( read_p4_b6.aoi_r2_w1 A2 ) ( read_p0_b6.aoi_r2_w1 A2 ) ( storage_2_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit7.storage ( read_p4_b7.aoi_r2_w1 A2 ) ( read_p0_b7.aoi_r2_w1 A2 ) ( storage_2_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.gclock ( storage_2_1_0.cg GCLK ) ( storage_2_1_0.bit7.bit CLK ) ( storage_2_1_0.bit6.bit CLK ) ( storage_2_1_0.bit5.bit CLK ) ( storage_2_1_0.bit4.bit CLK ) ( storage_2_1_0.bit3.bit CLK ) ( storage_2_1_0.bit2.bit CLK ) ++ ( storage_2_1_0.bit1.bit CLK ) ( storage_2_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_1_0.we ( storage_2_1_0.gcand Y ) ( storage_2_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_p3_b0.aoi_r2_w0 B2 ) ( read_p0_b0.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_p3_b1.aoi_r2_w0 B2 ) ( read_p0_b1.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_p3_b2.aoi_r2_w0 B2 ) ( read_p0_b2.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_p3_b3.aoi_r2_w0 B2 ) ( read_p0_b3.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_p3_b4.aoi_r2_w0 B2 ) ( read_p0_b4.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_p3_b5.aoi_r2_w0 B2 ) ( read_p0_b5.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_p3_b6.aoi_r2_w0 B2 ) ( read_p0_b6.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_p3_b7.aoi_r2_w0 B2 ) ( read_p0_b7.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_1_0.bit0.storage ( storage_3_1_0.bit0.bit QN ) ( read_p4_b0.aoi_r2_w1 B2 ) ( read_p0_b0.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit1.storage ( storage_3_1_0.bit1.bit QN ) ( read_p4_b1.aoi_r2_w1 B2 ) ( read_p0_b1.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit2.storage ( storage_3_1_0.bit2.bit QN ) ( read_p4_b2.aoi_r2_w1 B2 ) ( read_p0_b2.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit3.storage ( storage_3_1_0.bit3.bit QN ) ( read_p4_b3.aoi_r2_w1 B2 ) ( read_p0_b3.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit4.storage ( storage_3_1_0.bit4.bit QN ) ( read_p4_b4.aoi_r2_w1 B2 ) ( read_p0_b4.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit5.storage ( storage_3_1_0.bit5.bit QN ) ( read_p4_b5.aoi_r2_w1 B2 ) ( read_p0_b5.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit6.storage ( storage_3_1_0.bit6.bit QN ) ( read_p4_b6.aoi_r2_w1 B2 ) ( read_p0_b6.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit7.storage ( storage_3_1_0.bit7.bit QN ) ( read_p4_b7.aoi_r2_w1 B2 ) ( read_p0_b7.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.gclock ( storage_3_1_0.cg GCLK ) ( storage_3_1_0.bit7.bit CLK ) ( storage_3_1_0.bit6.bit CLK ) ( storage_3_1_0.bit5.bit CLK ) ( storage_3_1_0.bit4.bit CLK ) ( storage_3_1_0.bit3.bit CLK ) ( storage_3_1_0.bit2.bit CLK ) ++ ( storage_3_1_0.bit1.bit CLK ) ( storage_3_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_1_0.we ( storage_3_1_0.gcand Y ) ( storage_3_1_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_0_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_1_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_2_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_3_1_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_3_1_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_1_0.gcand B ) ( storage_2_0_0.gcand B ) ( storage_1_1_0.gcand B ) ( storage_1_0_0.gcand B ) ++ ( storage_0_1_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_rb_asap7.tcl b/src/ram/test/make_8x8_rb_asap7.tcl +new file mode 100644 +index 0000000000..5cb1f35e7d +--- /dev/null ++++ b/src/ram/test/make_8x8_rb_asap7.tcl +@@ -0,0 +1,36 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees: a plain one and a banked one, an address and data per ++# bank, over 4 banks of 2 words, word 0 reading 0. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_rb_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 1 \ ++ -rb_ports 1 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -banks 4 \ ++ -bank_columns 2 \ ++ -zero_word 0 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_rb_asap7.def] ++write_def $def_file ++diff_files make_8x8_rb_asap7.defok $def_file ++ ++diff_files make_8x8_rb_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_rb_asap7_behavioral.vok b/src/ram/test/make_8x8_rb_asap7_behavioral.vok +new file mode 100644 +index 0000000000..e8b35b7a5e +--- /dev/null ++++ b/src/ram/test/make_8x8_rb_asap7_behavioral.vok +@@ -0,0 +1,66 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q, ++ addr_w, ++ addr_r0, ++ addr_rb0_b0, ++ addr_rb0_b1, ++ addr_rb0_b2, ++ addr_rb0_b3, ++ we, ++ Qrb0_b0, ++ Qrb0_b1, ++ Qrb0_b2, ++ Qrb0_b3 ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q; ++ output reg [7:0] Qrb0_b0; ++ output reg [7:0] Qrb0_b1; ++ output reg [7:0] Qrb0_b2; ++ output reg [7:0] Qrb0_b3; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [0:0] addr_rb0_b0; ++ input [0:0] addr_rb0_b1; ++ input [0:0] addr_rb0_b2; ++ input [0:0] addr_rb0_b3; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i] && addr_w != 0) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Qrb0_b0 = (0 + addr_rb0_b0) == 0 ? 8'd0 : mem[0 + addr_rb0_b0]; ++ end ++ ++ always @(*) begin ++ Qrb0_b1 = (2 + addr_rb0_b1) == 0 ? 8'd0 : mem[2 + addr_rb0_b1]; ++ end ++ ++ always @(*) begin ++ Qrb0_b2 = (4 + addr_rb0_b2) == 0 ? 8'd0 : mem[4 + addr_rb0_b2]; ++ end ++ ++ always @(*) begin ++ Qrb0_b3 = (6 + addr_rb0_b3) == 0 ? 8'd0 : mem[6 + addr_rb0_b3]; ++ end ++ ++ always @(*) begin ++ Q = addr_r0 == 0 ? 8'd0 : mem[addr_r0]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index de4890a1af..35912fc218 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -10,5 +10,6 @@ record_tests { + make_8x8_2r1w_zero_asap7 + make_8x8_2r1w_reset_asap7 + make_8x8_2r1w_banks_asap7 ++ make_8x8_rb_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 0653fc454..76784bb51 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -179,6 +179,7 @@ test_suite( "@openroad//src/ram/test:make_8x8_2r1w_reset_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_rb_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_sky130-tcl_test", ], ) diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 8ac1c75dd..96a425c82 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -159,7 +159,8 @@ ASAP7 = { # with an asynchronous reset to a value of both 0s and 1s (patch 0014), # on Nangate45's set/reset flop and asap7's, which stores !D; and in # banks (patch 0015), contiguous and interleaved, side by side and -# stacked, tristate and AND-OR, and 12 words in banks of 3. +# stacked, tristate and AND-OR, and 12 words in banks of 3; and with a +# banked read port beside a plain one (patch 0016). [ [ genrule( @@ -237,5 +238,7 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_banks_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2 -bank_order interleaved -zero_word 0", "tb_ram_2w", 8), ("ram_2w_banks12_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2", "tb_ram_2w", 12), ("ram_2w_banks12", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 4 -bank_order interleaved", "tb_ram_2w", 12), + ("ram_rb", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 2 -bank_order interleaved -rb_ports 1", "tb_ram_rb", 8), + ("ram_rb_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2 -rb_ports 1 -zero_word 0", "tb_ram_rb", 8), ] ] diff --git a/test/regfile/sim/tb_ram_rb.cc b/test/regfile/sim/tb_ram_rb.cc new file mode 100644 index 000000000..61cfa006e --- /dev/null +++ b/test/regfile/sim/tb_ram_rb.cc @@ -0,0 +1,50 @@ +// Random writes on both ports, a quarter to the same word, and every +// cycle a plain read and a read of every bank at its own index, the +// netlist's outputs compared with the behavioral model's. Every word is +// written once first, unchecked. +#include +#include +#include + +#include "Vtb_ram_rb.h" + +int main() { + Vtb_ram_rb tb; + std::mt19937 rng(1); + int bad = 0; + int cycle = 0; + auto step = [&](bool check, bool we0, int a0, int d0, bool we1, int a1, + int d1) { + tb.clk = 0; + tb.we0 = we0; + tb.addr_w0 = a0; + tb.D0 = d0; + tb.we1 = we1; + tb.addr_w1 = a1; + tb.D1 = d1; + tb.addr_r0 = rng() % 8; + tb.addr_rb0_b0 = rng() % 2; + tb.addr_rb0_b1 = rng() % 2; + tb.addr_rb0_b2 = rng() % 2; + tb.addr_rb0_b3 = rng() % 2; + tb.eval(); + if (check && (tb.Q_model != tb.Q_gen || tb.Qrb_model != tb.Qrb_gen)) { + std::printf("cycle %d: model %02x %08x, generated %02x %08x\n", cycle, + tb.Q_model, tb.Qrb_model, tb.Q_gen, tb.Qrb_gen); + ++bad; + } + tb.clk = 1; + tb.eval(); + ++cycle; + }; + for (int w = 0; w < 8; ++w) { + step(false, true, w, rng() & 0xff, false, 0, 0); + } + for (int i = 0; i < 20000 && bad < 10; ++i) { + const int a0 = rng() % 8; + const int a1 = rng() % 4 == 0 ? a0 : rng() % 8; + step(true, rng() % 2, a0, rng() & 0xff, rng() % 2, a1, rng() & 0xff); + } + std::printf("%d cycles, %d mismatches\n", cycle, bad); + return bad == 0 ? 0 : 1; +} diff --git a/test/regfile/sim/tb_ram_rb.v b/test/regfile/sim/tb_ram_rb.v new file mode 100644 index 000000000..714ee1ac8 --- /dev/null +++ b/test/regfile/sim/tb_ram_rb.v @@ -0,0 +1,38 @@ +// generate_ram with two write ports, a plain read port and a banked one +// (-rb_ports 1) over 4 banks of 2 words: its behavioral model (RAM8x8) +// and its netlist (RAM8x8_gen) on the same inputs. +module tb_ram_rb ( + input clk, + input [7:0] D0, + input [7:0] D1, + input [2:0] addr_w0, + input [2:0] addr_w1, + input [2:0] addr_r0, + input addr_rb0_b0, + input addr_rb0_b1, + input addr_rb0_b2, + input addr_rb0_b3, + input we0, + input we1, + output [7:0] Q_model, + output [7:0] Q_gen, + output [31:0] Qrb_model, + output [31:0] Qrb_gen +); + RAM8x8 model ( + .clk(clk), .D0(D0), .D1(D1), .Q(Q_model), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1), + .addr_rb0_b0(addr_rb0_b0), .addr_rb0_b1(addr_rb0_b1), + .addr_rb0_b2(addr_rb0_b2), .addr_rb0_b3(addr_rb0_b3), + .Qrb0_b0(Qrb_model[7:0]), .Qrb0_b1(Qrb_model[15:8]), + .Qrb0_b2(Qrb_model[23:16]), .Qrb0_b3(Qrb_model[31:24]) + ); + RAM8x8_gen gen ( + .clk(clk), .D0(D0), .D1(D1), .Q(Q_gen), .addr_w0(addr_w0), + .addr_w1(addr_w1), .addr_r0(addr_r0), .we0(we0), .we1(we1), + .addr_rb0_b0(addr_rb0_b0), .addr_rb0_b1(addr_rb0_b1), + .addr_rb0_b2(addr_rb0_b2), .addr_rb0_b3(addr_rb0_b3), + .Qrb0_b0(Qrb_gen[7:0]), .Qrb0_b1(Qrb_gen[15:8]), + .Qrb0_b2(Qrb_gen[23:16]), .Qrb0_b3(Qrb_gen[31:24]) + ); +endmodule From 7c41ace0e544de3a1b81c4f7676a6120004a911b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 09:12:59 +0200 Subject: [PATCH 16/26] ram: generate_ram -read_latency, registered read addresses (patch 0017) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The seventh generate_regfile feature carried onto generate_ram, on 0016: -read_latency 1 registers every read port's address, a plain positive-edge flop per bit in the address inverter's cell, as XiangShan's register files read. A flop giving the address inverted (asap7's DFFHQNx1) swaps the decoder's literals instead of adding a cell. The storage flop serves where it is a plain one: findMaster passes over two-output cells, as Nangate45's flops all are. Tests: make_8x8_rb_latency_asap7 in generate_ram's format; registered reads simulated on Nangate45 (Q) and asap7 (QN, banks, a banked read port), 20 008 cycles each, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + patches/0017-openroad-ram-read-latency.patch | 1187 ++++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 6 +- 4 files changed, 1196 insertions(+), 1 deletion(-) create mode 100644 patches/0017-openroad-ram-read-latency.patch diff --git a/MODULE.bazel b/MODULE.bazel index 6ca23cfbb..806d2993e 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -150,6 +150,9 @@ archive_override( # 0016: generate_ram -rb_ports, read ports with an address and data # per bank. On 0015 (OpenROAD #11669); not upstreamed. "//patches:0016-openroad-ram-banked-read-ports.patch", + # 0017: generate_ram -read_latency 1, registered read addresses. On + # 0016 (OpenROAD #11669); not upstreamed. + "//patches:0017-openroad-ram-read-latency.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0017-openroad-ram-read-latency.patch b/patches/0017-openroad-ram-read-latency.patch new file mode 100644 index 000000000..6d406b39d --- /dev/null +++ b/patches/0017-openroad-ram-read-latency.patch @@ -0,0 +1,1187 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -read_latency, registered read addresses + +-read_latency 1 registers every read port's address: a plain +positive-edge flop per address bit, found by its ff group, in the +address inverter's cell; the data follows a cycle after the address, +as XiangShan's register files read. Where the flop gives the address +inverted (asap7's DFFHQNx1) the decoders take the flop's output as the +complement and the inverter makes the true literal, so no cell is +added. The behavioral model registers the addresses the same way. Not +with -column_mux_ratio above 1 or with read/write ports (RAM-0072). + +The seventh of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 5f4dcdaa51..9b6f2bbc35 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -50,6 +50,7 @@ generate_ram [-mask_size bits] + [-bank_columns count] + [-bank_order contiguous|interleaved] + [-rb_ports count] ++ [-read_latency 0|1] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -80,6 +81,7 @@ generate_ram [-mask_size bits] + | `-reset_value` | Resets every word to `value` asynchronously, through a reset port at the storage flop's own polarity (`rst_n` or `rst`); each bit's flop is cleared or preset, the other pin held off. The storage cell has both an asynchronous clear and preset. A parent adapts a reset of another polarity, or a synchronous one, to it. Not with `-use_latch`. Default: no reset. | + | `-banks`, `-bank_columns`, `-bank_order` | The words in `banks` banks, contiguous or interleaved in the address, `bank_columns` of them side by side and the rest stacked. With banks each port decodes every word's whole address, so a bank need not be a power of two words. Not with `-column_mux_ratio` above 1 or `-use_latch`. Default: one bank. | + | `-rb_ports` | Banked read ports, with `-banks`: each an address and a data output per bank (`addr_rb_b`, `Qrb_b`), the address the word's index in its bank, every bank read independently. Default: 0. | ++| `-read_latency` | `1` registers every read port's address, a plain positive-edge flop per address bit, so the data follows a cycle after the address. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 6d9e6253d3..fe22f91a04 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -116,7 +116,8 @@ class RamGen + int banks = 1, + int bank_columns = 1, + const std::string& bank_order = "contiguous", +- int rb_ports = 0); ++ int rb_ports = 0, ++ int read_latency = 0); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -362,6 +363,18 @@ class RamGen + // the bank of the word at (row, word in the row), and its index there + int bankAt(int row, int word_idx) const; + int indexInBank(int row) const; ++ // -read_latency 1: each read port's address through a flop (a plain ++ // positive-edge one) in the address inverter's cell. The decoders read ++ // addr_true_ (the address, or the flop's output) and its complement; ++ // where the flop's output is inverted the complement is the flop's and ++ // the inverter makes the true one. ++ int read_latency_{0}; ++ odb::dbMaster* addr_flop_cell_{nullptr}; ++ std::string addr_flop_d_, addr_flop_clk_, addr_flop_q_; ++ bool addr_flop_inverted_{false}; ++ odb::dbNet* clock_net_{nullptr}; ++ std::vector> addr_true_; ++ std::vector> addr_flop_out_; // or nullptr + // An asynchronous reset to reset_value_ (a word's value, every word): + // each bit's flop is cleared or preset by the reset port, the other + // pin held off. The pins come from the flop's ff group; clear_reads_ +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 9d75d28322..d5521b13ab 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -819,14 +819,29 @@ std::unique_ptr RamGen::makeInverterColumn( + continue; + } + auto inv_grid_cell = std::make_unique(); ++ const int a = num_word_bits + bit; ++ dbNet* flop_out = addr_flop_out_[p][a]; ++ if (flop_out) { ++ // -read_latency 1: the address through a flop, beside its inverter ++ makeInst(inv_grid_cell.get(), ++ fmt::format("decoder_p{}", p), ++ fmt::format("addr_reg_p{}_a{}", p, bit), ++ addr_flop_cell_, ++ {{addr_flop_d_, addr_inputs_[p][a]->getNet()}, ++ {addr_flop_clk_, clock_net_}, ++ {addr_flop_q_, flop_out}}); ++ } ++ // the inverter: the address (or the flop's) in, its complement out; ++ // from a flop holding the complement, the address out ++ const bool from_complement = flop_out && addr_flop_inverted_; + makeInst(inv_grid_cell.get(), + fmt::format("decoder_p{}", p), + fmt::format("inv_p{}_a{}", p, bit), + inv_cell_, + {{inv_ports_[{PortRoleType::DataIn, 0}], +- addr_inputs_[p][num_word_bits + bit]->getNet()}, ++ from_complement ? inv_addr_nets[p][a] : addr_true_[p][a]}, + {inv_ports_[{PortRoleType::DataOut, 0}], +- inv_addr_nets[p][num_word_bits + bit]}}); ++ from_complement ? addr_true_[p][a] : inv_addr_nets[p][a]}}); + cell_inv_layout->addCell(std::move(inv_grid_cell)); + } + // add fillers between bit groups +@@ -1782,7 +1797,8 @@ void RamGen::generate(const int mask_size, + const int banks, + const int bank_columns, + const std::string& bank_order, +- const int rb_ports) ++ const int rb_ports, ++ const int read_latency) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1811,6 +1827,18 @@ void RamGen::generate(const int mask_size, + } + words_per_bank_ = num_words / banks_; + rb_ports_ = rb_ports; ++ read_latency_ = read_latency; ++ if (read_latency_ > 0) { ++ if (read_latency_ != 1) { ++ logger_->error(RAM, 71, "-read_latency is 0 or 1."); ++ } ++ if (column_mux_ratio_arg > 1 || rw_ports > 0) { ++ logger_->error(RAM, ++ 72, ++ "-read_latency 1 is not supported with -column_mux_ratio " ++ "above 1 or with read/write ports."); ++ } ++ } + r_plain_ = rw_ports + r_ports; + if (rb_ports_ > 0 && !banked_) { + logger_->error(RAM, 70, "-rb_ports needs -banks."); +@@ -1919,6 +1947,47 @@ void RamGen::generate(const int mask_size, + + findMasters(); + ++ // -read_latency 1: a plain positive-edge flop for the read addresses ++ if (read_latency_ > 0) { ++ // a plain flop: positive-edge, no clear or preset ++ auto plain = [](const sta::LibertyCell* cell) { ++ for (const auto& seq : cell->sequentials()) { ++ if (seq.isRegister() && !seq.clear() && !seq.preset() && seq.clock() ++ && seq.clock()->op() == sta::FuncExpr::Op::port) { ++ return true; ++ } ++ } ++ return false; ++ }; ++ // the storage cell where it is one (findMaster passes over cells with ++ // two outputs, as Nangate45's flops all are), else the smallest ++ if (storage_cell_ ++ && plain(network_->libertyCell(network_->dbToSta(storage_cell_)))) { ++ addr_flop_cell_ = storage_cell_; ++ } else { ++ addr_flop_cell_ = findMaster( ++ [plain](sta::LibertyPort* port) { ++ return port->isRegOutput() && plain(port->libertyCell()); ++ }, ++ "address flop"); ++ } ++ auto ports = buildPortMap(addr_flop_cell_, &addr_flop_inverted_); ++ auto liberty = network_->libertyCell(network_->dbToSta(addr_flop_cell_)); ++ for (const auto& seq : liberty->sequentials()) { ++ if (seq.isRegister()) { ++ // the D pin (buildPortMap's polarity already counts a "!D") ++ const sta::FuncExpr* d = seq.data(); ++ if (d->op() == sta::FuncExpr::Op::not_) { ++ d = d->left(); ++ } ++ addr_flop_d_ = d->port()->name(); ++ break; ++ } ++ } ++ addr_flop_clk_ = ports[{PortRoleType::Clock, 0}]; ++ addr_flop_q_ = ports[{PortRoleType::DataOut, 0}]; ++ } ++ + // A zero word reads 0 and drops its writes, as a RISC-V x0: its row + // has no flops, and the read trees leave it out. + if (zero_word_ >= 0) { +@@ -1971,6 +2040,7 @@ void RamGen::generate(const int mask_size, + ram_grid_.setNumLayouts(col_cell_count); + + auto clock = makeBTerm("clk", dbIoType::INPUT); ++ clock_net_ = clock->getNet(); + + // -reset_value: an asynchronous reset at the storage flop's own + // polarity, rst_n or rst; a parent adapts any other reset to it +@@ -2014,7 +2084,10 @@ void RamGen::generate(const int mask_size, + int r_sel_idx = 0; + int w_sel_idx = 0; + ++ addr_inputs_.clear(); + addr_inputs_.resize(total_ports); ++ addr_true_.assign(total_ports, {}); ++ addr_flop_out_.assign(total_ports, {}); + vector> inv_addr_nets(total_ports); + // for column muxing, deocder input nets uses only the upper address bits + // (num_row_bits) to determine row +@@ -2048,12 +2121,27 @@ void RamGen::generate(const int mask_size, + + addr_inputs_[p].resize(port_inputs); + inv_addr_nets[p].resize(port_inputs); ++ addr_true_[p].resize(port_inputs); ++ addr_flop_out_[p].assign(port_inputs, nullptr); ++ const bool registered = read_latency_ > 0 && p >= rw_ports + w_ports; + + for (int i = 0; i < port_inputs; ++i) { + addr_inputs_[p][i] + = makeBTerm(fmt::format("{}[{}]", port_prefix, i), dbIoType::INPUT); +- inv_addr_nets[p][i] +- = makeNet(port_prefix, fmt::format("inv_addr[{}]", i)); ++ if (registered && addr_flop_inverted_) { ++ // the flop holds the complement; the inverter makes the address ++ addr_flop_out_[p][i] = inv_addr_nets[p][i] ++ = makeNet(port_prefix, fmt::format("inv_addr[{}]", i)); ++ addr_true_[p][i] = makeNet(port_prefix, fmt::format("addr_q[{}]", i)); ++ } else { ++ inv_addr_nets[p][i] ++ = makeNet(port_prefix, fmt::format("inv_addr[{}]", i)); ++ addr_true_[p][i] = addr_inputs_[p][i]->getNet(); ++ if (registered) { ++ addr_flop_out_[p][i] = addr_true_[p][i] ++ = makeNet(port_prefix, fmt::format("addr_q[{}]", i)); ++ } ++ } + } + + // inputs to decoders: with banks, every word's whole address, one +@@ -2073,7 +2161,7 @@ void RamGen::generate(const int mask_size, + literals.resize(port_inputs); + for (int input = 0; input < port_inputs; ++input) { + literals[input] = ((word >> input) & 1) +- ? addr_inputs_[p][input]->getNet() ++ ? addr_true_[p][input] + : inv_addr_nets[p][input]; + } + } +@@ -2092,7 +2180,7 @@ void RamGen::generate(const int mask_size, + = inv_addr_nets[p][num_word_bits + input]; + } else { // puts original input in invert nets + decoder_input_nets[p][row][input] +- = addr_inputs_[p][num_word_bits + input]->getNet(); ++ = addr_true_[p][num_word_bits + input]; + } + row_num /= 2; + } +@@ -2947,6 +3035,50 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + } + } + ++ // -read_latency 1: every read address registered, the reads from the ++ // registered ones (addr_r0 -> addr_r0_q) ++ if (read_latency_ > 0) { ++ std::string registers; ++ auto registered = [&](const std::string& name, int width) { ++ registers += fmt::format( ++ " reg [{}:0] {}_q;\n always @(posedge clk) {}_q <= {};\n", ++ width - 1, ++ name, ++ name, ++ name); ++ // whole words only: addr_r1 is not part of addr_r10 ++ std::string out; ++ size_t at = 0; ++ while (true) { ++ size_t hit = read_port_logic.find(name, at); ++ if (hit == std::string::npos) { ++ out += read_port_logic.substr(at); ++ break; ++ } ++ const size_t end = hit + name.size(); ++ const bool whole = end >= read_port_logic.size() ++ || !(std::isalnum(static_cast( ++ read_port_logic[end])) ++ || read_port_logic[end] == '_'); ++ out += read_port_logic.substr(at, end - at); ++ if (whole) { ++ out += "_q"; ++ } ++ at = end; ++ } ++ read_port_logic = out; ++ }; ++ for (int i = 0; i < r_ports; ++i) { ++ registered(fmt::format("addr_r{}", i), address_width); ++ } ++ for (int k = 0; k < rb_ports_; ++k) { ++ for (int b = 0; b < banks_; ++b) { ++ registered(fmt::format("addr_rb{}_b{}", k, b), bank_bits); ++ } ++ } ++ read_port_logic = registers + "\n" + read_port_logic; ++ } ++ + // Write logic, the ports in order: where two write the same word in a + // cycle, the last one's data is kept. + std::string data_declarations; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 037e28f5ff..4494870fdb 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -49,7 +49,8 @@ generate_ram_netlist_cmd(int mask_size, + const int banks, + const int bank_columns, + const char* bank_order, +- const int rb_ports) ++ const int rb_ports, ++ const int read_latency) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -102,7 +103,8 @@ generate_ram_netlist_cmd(int mask_size, + ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, +- reset_value, banks, bank_columns, bank_order, rb_ports); ++ reset_value, banks, bank_columns, bank_order, rb_ports, ++ read_latency); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 3466fe562c..75d6fbb387 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -14,12 +14,14 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-bank_columns count] + [-bank_order contiguous|interleaved] + [-rb_ports count] ++ [-read_latency 0|1] + [-zero_word word] + [-reset_value value] + [-banks count] + [-bank_columns count] + [-bank_order contiguous|interleaved] + [-rb_ports count] ++ [-read_latency 0|1] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -33,7 +35,7 @@ proc generate_ram_netlist { args } { + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports } flags {} ++ -banks -bank_columns -bank_order -rb_ports -read_latency } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -179,6 +181,12 @@ proc generate_ram_netlist { args } { + if { [info exists keys(-bank_columns)] } { + set bank_columns $keys(-bank_columns) + } ++ # A read latency of 1: the read addresses registered. ++ set read_latency 0 ++ if { [info exists keys(-read_latency)] } { ++ set read_latency $keys(-read_latency) ++ } ++ + # Banked read ports: an address and a data output per bank. + set rb_ports 0 + if { [info exists keys(-rb_ports)] } { +@@ -195,7 +203,7 @@ proc generate_ram_netlist { args } { + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ +- $rb_ports ++ $rb_ports $read_latency + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -230,7 +238,7 @@ proc generate_ram { args } { + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports } flags {} ++ -banks -bank_columns -bank_order -rb_ports -read_latency } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -279,7 +287,7 @@ proc generate_ram { args } { + lappend ram_netlist_args -reset_value $keys(-reset_value) + } + +- foreach key {-banks -bank_columns -bank_order -rb_ports} { ++ foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index cd2a6d7cdb..83fa973277 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_rb_latency_asap7", + "make_8x8_rb_asap7", + "make_8x8_2r1w_banks_asap7", + "make_8x8_2r1w_reset_asap7", +@@ -116,6 +117,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_rb_asap7_behavioral.vok", + ], ++ "make_8x8_rb_latency_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_rb_latency_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_rb_latency_asap7.defok b/src/ram/test/make_8x8_rb_latency_asap7.defok +new file mode 100644 +index 0000000000..bca375a052 +--- /dev/null ++++ b/src/ram/test/make_8x8_rb_latency_asap7.defok +@@ -0,0 +1,627 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 4179 135 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 774 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 774 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 774 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 774 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 774 BY 1 STEP 5 0 ; ++COMPONENTS 247 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 1382 108 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1728 108 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 2073 108 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 2419 108 ) N ; ++ - decoder_p0.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3067 0 ) N ; ++ - decoder_p0.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3132 0 ) N ; ++ - decoder_p0.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3067 27 ) FS ; ++ - decoder_p0.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3132 27 ) FS ; ++ - decoder_p0.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3067 54 ) N ; ++ - decoder_p0.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3132 54 ) N ; ++ - decoder_p0.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3067 81 ) FS ; ++ - decoder_p0.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3132 81 ) FS ; ++ - decoder_p0.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3099 0 ) N ; ++ - decoder_p0.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3164 0 ) N ; ++ - decoder_p0.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3099 27 ) FS ; ++ - decoder_p0.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3164 27 ) FS ; ++ - decoder_p0.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3099 54 ) N ; ++ - decoder_p0.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3164 54 ) N ; ++ - decoder_p0.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3099 81 ) FS ; ++ - decoder_p0.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3164 81 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 3542 54 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 3542 27 ) FS ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 3542 0 ) N ; ++ - decoder_p1.addr_reg_p1_a0 DFFHQNx1_ASAP7_75t_R + PLACED ( 3558 54 ) N ; ++ - decoder_p1.addr_reg_p1_a1 DFFHQNx1_ASAP7_75t_R + PLACED ( 3558 27 ) FS ; ++ - decoder_p1.addr_reg_p1_a2 DFFHQNx1_ASAP7_75t_R + PLACED ( 3558 0 ) N ; ++ - decoder_p1.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3240 0 ) N ; ++ - decoder_p1.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3304 0 ) N ; ++ - decoder_p1.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3240 27 ) FS ; ++ - decoder_p1.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3304 27 ) FS ; ++ - decoder_p1.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3240 54 ) N ; ++ - decoder_p1.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3304 54 ) N ; ++ - decoder_p1.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3240 81 ) FS ; ++ - decoder_p1.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3304 81 ) FS ; ++ - decoder_p1.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3272 0 ) N ; ++ - decoder_p1.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3337 0 ) N ; ++ - decoder_p1.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3272 27 ) FS ; ++ - decoder_p1.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3337 27 ) FS ; ++ - decoder_p1.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3272 54 ) N ; ++ - decoder_p1.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3337 54 ) N ; ++ - decoder_p1.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3272 81 ) FS ; ++ - decoder_p1.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3337 81 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 3666 54 ) N ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 3666 27 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 3666 0 ) N ; ++ - decoder_p2.addr_reg_p2_a0 DFFHQNx1_ASAP7_75t_R + PLACED ( 3682 54 ) N ; ++ - decoder_p2.buf_word0 HB1xp67_ASAP7_75t_R + PLACED ( 3391 0 ) N ; ++ - decoder_p2.buf_word2 HB1xp67_ASAP7_75t_R + PLACED ( 3391 27 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 3790 54 ) N ; ++ - decoder_p3.addr_reg_p3_a0 DFFHQNx1_ASAP7_75t_R + PLACED ( 3807 54 ) N ; ++ - decoder_p3.buf_word1 HB1xp67_ASAP7_75t_R + PLACED ( 3434 0 ) N ; ++ - decoder_p3.buf_word3 HB1xp67_ASAP7_75t_R + PLACED ( 3434 27 ) FS ; ++ - decoder_p3.inv_p3_a0 INVx1_ASAP7_75t_R + PLACED ( 3915 54 ) N ; ++ - decoder_p4.addr_reg_p4_a0 DFFHQNx1_ASAP7_75t_R + PLACED ( 3931 54 ) N ; ++ - decoder_p4.buf_word4 HB1xp67_ASAP7_75t_R + PLACED ( 3477 54 ) N ; ++ - decoder_p4.buf_word6 HB1xp67_ASAP7_75t_R + PLACED ( 3477 81 ) FS ; ++ - decoder_p4.inv_p4_a0 INVx1_ASAP7_75t_R + PLACED ( 4039 54 ) N ; ++ - decoder_p5.addr_reg_p5_a0 DFFHQNx1_ASAP7_75t_R + PLACED ( 4055 54 ) N ; ++ - decoder_p5.buf_word5 HB1xp67_ASAP7_75t_R + PLACED ( 3520 54 ) N ; ++ - decoder_p5.buf_word7 HB1xp67_ASAP7_75t_R + PLACED ( 3520 81 ) FS ; ++ - decoder_p5.inv_p5_a0 INVx1_ASAP7_75t_R + PLACED ( 4163 54 ) N ; ++ - read_p0_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - read_p0_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 280 0 ) N ; ++ - read_p0_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_p0_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_p0_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - read_p0_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 626 0 ) N ; ++ - read_p0_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_p0_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_p0_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - read_p0_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 972 0 ) N ; ++ - read_p0_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_p0_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_p0_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - read_p0_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 0 ) N ; ++ - read_p0_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_p0_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_p0_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1382 0 ) N ; ++ - read_p0_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1663 0 ) N ; ++ - read_p0_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1490 54 ) N ; ++ - read_p0_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1663 54 ) N ; ++ - read_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1490 27 ) FS ; ++ - read_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1663 27 ) FS ; ++ - read_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1490 81 ) FS ; ++ - read_p0_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1728 0 ) N ; ++ - read_p0_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2008 0 ) N ; ++ - read_p0_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 54 ) N ; ++ - read_p0_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2008 54 ) N ; ++ - read_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1836 27 ) FS ; ++ - read_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2008 27 ) FS ; ++ - read_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1836 81 ) FS ; ++ - read_p0_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2073 0 ) N ; ++ - read_p0_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2354 0 ) N ; ++ - read_p0_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2181 54 ) N ; ++ - read_p0_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2354 54 ) N ; ++ - read_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2181 27 ) FS ; ++ - read_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2354 27 ) FS ; ++ - read_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2181 81 ) FS ; ++ - read_p0_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2419 0 ) N ; ++ - read_p0_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2700 0 ) N ; ++ - read_p0_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2527 54 ) N ; ++ - read_p0_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2700 54 ) N ; ++ - read_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2527 27 ) FS ; ++ - read_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2700 27 ) FS ; ++ - read_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2527 81 ) FS ; ++ - read_p1_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 32 0 ) N ; ++ - read_p1_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 378 0 ) N ; ++ - read_p1_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 723 0 ) N ; ++ - read_p1_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1069 0 ) N ; ++ - read_p1_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1414 0 ) N ; ++ - read_p1_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1760 0 ) N ; ++ - read_p1_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2106 0 ) N ; ++ - read_p1_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2451 0 ) N ; ++ - read_p2_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 313 0 ) N ; ++ - read_p2_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 658 0 ) N ; ++ - read_p2_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 0 ) N ; ++ - read_p2_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 0 ) N ; ++ - read_p2_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1695 0 ) N ; ++ - read_p2_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2041 0 ) N ; ++ - read_p2_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2386 0 ) N ; ++ - read_p2_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2732 0 ) N ; ++ - read_p3_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_p3_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_p3_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_p3_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_p3_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1522 54 ) N ; ++ - read_p3_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 54 ) N ; ++ - read_p3_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2214 54 ) N ; ++ - read_p3_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 2559 54 ) N ; ++ - read_p4_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_p4_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_p4_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_p4_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_p4_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1695 54 ) N ; ++ - read_p4_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2041 54 ) N ; ++ - read_p4_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2386 54 ) N ; ++ - read_p4_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2732 54 ) N ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3196 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3218 0 ) N ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3196 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3218 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3196 54 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3218 54 ) N ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3196 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3218 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3369 0 ) N ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3369 27 ) FS ; ++ - sel_buf_r_p3.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3412 0 ) N ; ++ - sel_buf_r_p3.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3412 27 ) FS ; ++ - sel_buf_r_p4.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3456 54 ) N ; ++ - sel_buf_r_p4.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3456 81 ) FS ; ++ - sel_buf_r_p5.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3499 54 ) N ; ++ - sel_buf_r_p5.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3499 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3024 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3045 0 ) N ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3024 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3045 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3024 54 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3045 54 ) N ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3024 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3045 81 ) FS ; ++ - storage_0_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - storage_0_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - storage_0_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - storage_0_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - storage_0_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 0 ) N ; ++ - storage_0_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 0 ) N ; ++ - storage_0_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 0 ) N ; ++ - storage_0_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 0 ) N ; ++ - storage_0_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 0 ) N ; ++ - storage_0_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 27 ) FS ; ++ - storage_1_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 27 ) FS ; ++ - storage_1_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 27 ) FS ; ++ - storage_1_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 27 ) FS ; ++ - storage_1_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 27 ) FS ; ++ - storage_1_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 27 ) FS ; ++ - storage_1_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 54 ) N ; ++ - storage_2_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 54 ) N ; ++ - storage_2_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 54 ) N ; ++ - storage_2_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 54 ) N ; ++ - storage_2_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 54 ) N ; ++ - storage_2_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 54 ) N ; ++ - storage_2_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1728 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2073 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2419 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2764 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2862 81 ) FS ; ++ - storage_3_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1555 81 ) FS ; ++ - storage_3_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1900 81 ) FS ; ++ - storage_3_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2246 81 ) FS ; ++ - storage_3_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2592 81 ) FS ; ++ - storage_3_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 81 ) FS ; ++ - storage_3_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 81 ) FS ; ++END COMPONENTS ++PINS 60 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q[0] + NET Q[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[1] + NET Q[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[2] + NET Q[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[3] + NET Q[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[4] + NET Q[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[5] + NET Q[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[6] + NET Q[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q[7] + NET Q[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[0] + NET Qrb0_b0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[1] + NET Qrb0_b0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[2] + NET Qrb0_b0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[3] + NET Qrb0_b0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[4] + NET Qrb0_b0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[5] + NET Qrb0_b0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[6] + NET Qrb0_b0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b0[7] + NET Qrb0_b0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[0] + NET Qrb0_b1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[1] + NET Qrb0_b1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[2] + NET Qrb0_b1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[3] + NET Qrb0_b1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[4] + NET Qrb0_b1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[5] + NET Qrb0_b1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[6] + NET Qrb0_b1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b1[7] + NET Qrb0_b1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[0] + NET Qrb0_b2[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[1] + NET Qrb0_b2[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[2] + NET Qrb0_b2[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[3] + NET Qrb0_b2[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[4] + NET Qrb0_b2[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[5] + NET Qrb0_b2[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[6] + NET Qrb0_b2[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b2[7] + NET Qrb0_b2[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[0] + NET Qrb0_b3[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[1] + NET Qrb0_b3[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[2] + NET Qrb0_b3[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[3] + NET Qrb0_b3[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[4] + NET Qrb0_b3[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[5] + NET Qrb0_b3[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[6] + NET Qrb0_b3[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Qrb0_b3[7] + NET Qrb0_b3[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b0[0] + NET addr_rb0_b0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b1[0] + NET addr_rb0_b1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b2[0] + NET addr_rb0_b2[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_rb0_b3[0] + NET addr_rb0_b3[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 267 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_3_1_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_1_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ( storage_1_1_0.bit0.bit D ) ( storage_1_0_0.bit0.bit D ) ++ ( storage_0_1_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_3_1_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_1_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ( storage_1_1_0.bit1.bit D ) ( storage_1_0_0.bit1.bit D ) ++ ( storage_0_1_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_3_1_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_1_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ( storage_1_1_0.bit2.bit D ) ( storage_1_0_0.bit2.bit D ) ++ ( storage_0_1_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_3_1_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_1_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ( storage_1_1_0.bit3.bit D ) ( storage_1_0_0.bit3.bit D ) ++ ( storage_0_1_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_3_1_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_1_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ( storage_1_1_0.bit4.bit D ) ( storage_1_0_0.bit4.bit D ) ++ ( storage_0_1_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_3_1_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_1_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ( storage_1_1_0.bit5.bit D ) ( storage_1_0_0.bit5.bit D ) ++ ( storage_0_1_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_3_1_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_1_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ( storage_1_1_0.bit6.bit D ) ( storage_1_0_0.bit6.bit D ) ++ ( storage_0_1_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_3_1_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_1_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ( storage_1_1_0.bit7.bit D ) ( storage_1_0_0.bit7.bit D ) ++ ( storage_0_1_0.bit7.bit D ) + USE SIGNAL ; ++ - Q[0] ( PIN Q[0] ) ( read_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[1] ( PIN Q[1] ) ( read_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[2] ( PIN Q[2] ) ( read_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[3] ( PIN Q[3] ) ( read_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[4] ( PIN Q[4] ) ( read_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[5] ( PIN Q[5] ) ( read_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[6] ( PIN Q[6] ) ( read_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q[7] ( PIN Q[7] ) ( read_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Qrb0_b0[0] ( PIN Qrb0_b0[0] ) ( read_p1_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[1] ( PIN Qrb0_b0[1] ) ( read_p1_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[2] ( PIN Qrb0_b0[2] ) ( read_p1_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[3] ( PIN Qrb0_b0[3] ) ( read_p1_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[4] ( PIN Qrb0_b0[4] ) ( read_p1_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[5] ( PIN Qrb0_b0[5] ) ( read_p1_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[6] ( PIN Qrb0_b0[6] ) ( read_p1_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b0[7] ( PIN Qrb0_b0[7] ) ( read_p1_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b1[0] ( PIN Qrb0_b1[0] ) ( read_p2_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[1] ( PIN Qrb0_b1[1] ) ( read_p2_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[2] ( PIN Qrb0_b1[2] ) ( read_p2_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[3] ( PIN Qrb0_b1[3] ) ( read_p2_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[4] ( PIN Qrb0_b1[4] ) ( read_p2_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[5] ( PIN Qrb0_b1[5] ) ( read_p2_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[6] ( PIN Qrb0_b1[6] ) ( read_p2_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b1[7] ( PIN Qrb0_b1[7] ) ( read_p2_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b2[0] ( PIN Qrb0_b2[0] ) ( read_p3_b0.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[1] ( PIN Qrb0_b2[1] ) ( read_p3_b1.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[2] ( PIN Qrb0_b2[2] ) ( read_p3_b2.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[3] ( PIN Qrb0_b2[3] ) ( read_p3_b3.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[4] ( PIN Qrb0_b2[4] ) ( read_p3_b4.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[5] ( PIN Qrb0_b2[5] ) ( read_p3_b5.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[6] ( PIN Qrb0_b2[6] ) ( read_p3_b6.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b2[7] ( PIN Qrb0_b2[7] ) ( read_p3_b7.aoi_r2_w0 Y ) + USE SIGNAL ; ++ - Qrb0_b3[0] ( PIN Qrb0_b3[0] ) ( read_p4_b0.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[1] ( PIN Qrb0_b3[1] ) ( read_p4_b1.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[2] ( PIN Qrb0_b3[2] ) ( read_p4_b2.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[3] ( PIN Qrb0_b3[3] ) ( read_p4_b3.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[4] ( PIN Qrb0_b3[4] ) ( read_p4_b4.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[5] ( PIN Qrb0_b3[5] ) ( read_p4_b5.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[6] ( PIN Qrb0_b3[6] ) ( read_p4_b6.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - Qrb0_b3[7] ( PIN Qrb0_b3[7] ) ( read_p4_b7.aoi_r2_w1 Y ) + USE SIGNAL ; ++ - addr_r0.addr_q[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and0_word7 A ) ( decoder_p1.and0_word6 A ) ( decoder_p1.and0_word3 A ) ( decoder_p1.and0_word2 A ) + USE SIGNAL ; ++ - addr_r0.addr_q[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and0_word7 B ) ( decoder_p1.and0_word5 B ) ( decoder_p1.and0_word3 B ) ( decoder_p1.and0_word1 B ) + USE SIGNAL ; ++ - addr_r0.addr_q[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and1_word7 B ) ( decoder_p1.and1_word6 B ) ( decoder_p1.and1_word5 B ) ( decoder_p1.and1_word4 B ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.addr_reg_p1_a0 QN ) ( decoder_p1.and0_word5 A ) ( decoder_p1.and0_word4 A ) ( decoder_p1.and0_word1 A ) ( decoder_p1.and0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.addr_reg_p1_a1 QN ) ( decoder_p1.and0_word6 B ) ( decoder_p1.and0_word4 B ) ( decoder_p1.and0_word2 B ) ( decoder_p1.and0_word0 B ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.addr_reg_p1_a2 QN ) ( decoder_p1.and1_word3 B ) ( decoder_p1.and1_word2 B ) ( decoder_p1.and1_word1 B ) ( decoder_p1.and1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.addr_reg_p1_a0 D ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.addr_reg_p1_a1 D ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.addr_reg_p1_a2 D ) + USE SIGNAL ; ++ - addr_rb0_b0.addr_q[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.buf_word2 A ) + USE SIGNAL ; ++ - addr_rb0_b0.inv_addr[0] ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.addr_reg_p2_a0 QN ) ( decoder_p2.buf_word0 A ) + USE SIGNAL ; ++ - addr_rb0_b0[0] ( PIN addr_rb0_b0[0] ) ( decoder_p2.addr_reg_p2_a0 D ) + USE SIGNAL ; ++ - addr_rb0_b1.addr_q[0] ( decoder_p3.inv_p3_a0 Y ) ( decoder_p3.buf_word3 A ) + USE SIGNAL ; ++ - addr_rb0_b1.inv_addr[0] ( decoder_p3.inv_p3_a0 A ) ( decoder_p3.addr_reg_p3_a0 QN ) ( decoder_p3.buf_word1 A ) + USE SIGNAL ; ++ - addr_rb0_b1[0] ( PIN addr_rb0_b1[0] ) ( decoder_p3.addr_reg_p3_a0 D ) + USE SIGNAL ; ++ - addr_rb0_b2.addr_q[0] ( decoder_p4.inv_p4_a0 Y ) ( decoder_p4.buf_word6 A ) + USE SIGNAL ; ++ - addr_rb0_b2.inv_addr[0] ( decoder_p4.inv_p4_a0 A ) ( decoder_p4.addr_reg_p4_a0 QN ) ( decoder_p4.buf_word4 A ) + USE SIGNAL ; ++ - addr_rb0_b2[0] ( PIN addr_rb0_b2[0] ) ( decoder_p4.addr_reg_p4_a0 D ) + USE SIGNAL ; ++ - addr_rb0_b3.addr_q[0] ( decoder_p5.inv_p5_a0 Y ) ( decoder_p5.buf_word7 A ) + USE SIGNAL ; ++ - addr_rb0_b3.inv_addr[0] ( decoder_p5.inv_p5_a0 A ) ( decoder_p5.addr_reg_p5_a0 QN ) ( decoder_p5.buf_word5 A ) + USE SIGNAL ; ++ - addr_rb0_b3[0] ( PIN addr_rb0_b3[0] ) ( decoder_p5.addr_reg_p5_a0 D ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and0_word5 A ) ( decoder_p0.and0_word4 A ) ( decoder_p0.and0_word1 A ) ( decoder_p0.and0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and0_word6 B ) ( decoder_p0.and0_word4 B ) ( decoder_p0.and0_word2 B ) ( decoder_p0.and0_word0 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and1_word3 B ) ( decoder_p0.and1_word2 B ) ( decoder_p0.and1_word1 B ) ( decoder_p0.and1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and0_word7 A ) ( decoder_p0.and0_word6 A ) ( decoder_p0.and0_word3 A ) ( decoder_p0.and0_word2 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and0_word7 B ) ( decoder_p0.and0_word5 B ) ( decoder_p0.and0_word3 B ) ( decoder_p0.and0_word1 B ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and1_word7 B ) ( decoder_p0.and1_word6 B ) ( decoder_p0.and1_word5 B ) ( decoder_p0.and1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( decoder_p5.addr_reg_p5_a0 CLK ) ( decoder_p4.addr_reg_p4_a0 CLK ) ( decoder_p3.addr_reg_p3_a0 CLK ) ( decoder_p2.addr_reg_p2_a0 CLK ) ( decoder_p1.addr_reg_p1_a0 CLK ) ( decoder_p1.addr_reg_p1_a1 CLK ) ++ ( decoder_p1.addr_reg_p1_a2 CLK ) ( storage_3_1_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_1_0.cg CLK ) ( storage_2_0_0.cg CLK ) ( storage_1_1_0.cg CLK ) ( storage_1_0_0.cg CLK ) ( storage_0_1_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and1_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and1_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and1_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and1_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and1_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and1_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and1_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and1_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p0.y0_word0 ( decoder_p0.and1_word0 A ) ( decoder_p0.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word1 ( decoder_p0.and1_word1 A ) ( decoder_p0.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word2 ( decoder_p0.and1_word2 A ) ( decoder_p0.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word3 ( decoder_p0.and1_word3 A ) ( decoder_p0.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word4 ( decoder_p0.and1_word4 A ) ( decoder_p0.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word5 ( decoder_p0.and1_word5 A ) ( decoder_p0.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word6 ( decoder_p0.and1_word6 A ) ( decoder_p0.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word7 ( decoder_p0.and1_word7 A ) ( decoder_p0.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and1_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and1_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and1_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and1_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and1_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and1_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and1_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and1_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.y0_word0 ( decoder_p1.and1_word0 A ) ( decoder_p1.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word1 ( decoder_p1.and1_word1 A ) ( decoder_p1.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word2 ( decoder_p1.and1_word2 A ) ( decoder_p1.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word3 ( decoder_p1.and1_word3 A ) ( decoder_p1.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word4 ( decoder_p1.and1_word4 A ) ( decoder_p1.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word5 ( decoder_p1.and1_word5 A ) ( decoder_p1.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word6 ( decoder_p1.and1_word6 A ) ( decoder_p1.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word7 ( decoder_p1.and1_word7 A ) ( decoder_p1.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.buf_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.buf_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p3.word1 ( decoder_p3.buf_word1 Y ) ( sel_buf_r_p3.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p3.word3 ( decoder_p3.buf_word3 Y ) ( sel_buf_r_p3.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p4.word4 ( decoder_p4.buf_word4 Y ) ( sel_buf_r_p4.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p4.word6 ( decoder_p4.buf_word6 Y ) ( sel_buf_r_p4.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p5.word5 ( decoder_p5.buf_word5 Y ) ( sel_buf_r_p5.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p5.word7 ( decoder_p5.buf_word7 Y ) ( sel_buf_r_p5.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_p0_b7.aoi_r0_w0 A2 ) ( read_p0_b7.aoi_r0_w0 A1 ) ( read_p0_b6.aoi_r0_w0 A2 ) ( read_p0_b6.aoi_r0_w0 A1 ) ( read_p0_b5.aoi_r0_w0 A2 ) ( read_p0_b5.aoi_r0_w0 A1 ) ++ ( read_p0_b4.aoi_r0_w0 A2 ) ( read_p0_b4.aoi_r0_w0 A1 ) ( read_p0_b3.aoi_r0_w0 A2 ) ( read_p0_b3.aoi_r0_w0 A1 ) ( read_p0_b2.aoi_r0_w0 A2 ) ( read_p0_b2.aoi_r0_w0 A1 ) ( read_p0_b1.aoi_r0_w0 A2 ) ( read_p0_b1.aoi_r0_w0 A1 ) ++ ( read_p0_b0.aoi_r0_w0 A2 ) ( read_p0_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_p0_b7.aoi_r0_w1 A1 ) ( read_p0_b6.aoi_r0_w1 A1 ) ( read_p0_b5.aoi_r0_w1 A1 ) ( read_p0_b4.aoi_r0_w1 A1 ) ( read_p0_b3.aoi_r0_w1 A1 ) ( read_p0_b2.aoi_r0_w1 A1 ) ++ ( read_p0_b1.aoi_r0_w1 A1 ) ( read_p0_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_p0_b7.aoi_r0_w0 B1 ) ( read_p0_b6.aoi_r0_w0 B1 ) ( read_p0_b5.aoi_r0_w0 B1 ) ( read_p0_b4.aoi_r0_w0 B1 ) ( read_p0_b3.aoi_r0_w0 B1 ) ( read_p0_b2.aoi_r0_w0 B1 ) ++ ( read_p0_b1.aoi_r0_w0 B1 ) ( read_p0_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_p0_b7.aoi_r0_w1 B1 ) ( read_p0_b6.aoi_r0_w1 B1 ) ( read_p0_b5.aoi_r0_w1 B1 ) ( read_p0_b4.aoi_r0_w1 B1 ) ( read_p0_b3.aoi_r0_w1 B1 ) ( read_p0_b2.aoi_r0_w1 B1 ) ++ ( read_p0_b1.aoi_r0_w1 B1 ) ( read_p0_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_p0_b7.aoi_r2_w0 A1 ) ( read_p0_b6.aoi_r2_w0 A1 ) ( read_p0_b5.aoi_r2_w0 A1 ) ( read_p0_b4.aoi_r2_w0 A1 ) ( read_p0_b3.aoi_r2_w0 A1 ) ( read_p0_b2.aoi_r2_w0 A1 ) ++ ( read_p0_b1.aoi_r2_w0 A1 ) ( read_p0_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_p0_b7.aoi_r2_w1 A1 ) ( read_p0_b6.aoi_r2_w1 A1 ) ( read_p0_b5.aoi_r2_w1 A1 ) ( read_p0_b4.aoi_r2_w1 A1 ) ( read_p0_b3.aoi_r2_w1 A1 ) ( read_p0_b2.aoi_r2_w1 A1 ) ++ ( read_p0_b1.aoi_r2_w1 A1 ) ( read_p0_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_p0_b7.aoi_r2_w0 B1 ) ( read_p0_b6.aoi_r2_w0 B1 ) ( read_p0_b5.aoi_r2_w0 B1 ) ( read_p0_b4.aoi_r2_w0 B1 ) ( read_p0_b3.aoi_r2_w0 B1 ) ( read_p0_b2.aoi_r2_w0 B1 ) ++ ( read_p0_b1.aoi_r2_w0 B1 ) ( read_p0_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_p0_b7.aoi_r2_w1 B1 ) ( read_p0_b6.aoi_r2_w1 B1 ) ( read_p0_b5.aoi_r2_w1 B1 ) ( read_p0_b4.aoi_r2_w1 B1 ) ( read_p0_b3.aoi_r2_w1 B1 ) ( read_p0_b2.aoi_r2_w1 B1 ) ++ ( read_p0_b1.aoi_r2_w1 B1 ) ( read_p0_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_p1_b7.aoi_r0_w0 A2 ) ( read_p1_b7.aoi_r0_w0 A1 ) ( read_p1_b6.aoi_r0_w0 A2 ) ( read_p1_b6.aoi_r0_w0 A1 ) ( read_p1_b5.aoi_r0_w0 A2 ) ( read_p1_b5.aoi_r0_w0 A1 ) ++ ( read_p1_b4.aoi_r0_w0 A2 ) ( read_p1_b4.aoi_r0_w0 A1 ) ( read_p1_b3.aoi_r0_w0 A2 ) ( read_p1_b3.aoi_r0_w0 A1 ) ( read_p1_b2.aoi_r0_w0 A2 ) ( read_p1_b2.aoi_r0_w0 A1 ) ( read_p1_b1.aoi_r0_w0 A2 ) ( read_p1_b1.aoi_r0_w0 A1 ) ++ ( read_p1_b0.aoi_r0_w0 A2 ) ( read_p1_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_p1_b7.aoi_r0_w0 B1 ) ( read_p1_b6.aoi_r0_w0 B1 ) ( read_p1_b5.aoi_r0_w0 B1 ) ( read_p1_b4.aoi_r0_w0 B1 ) ( read_p1_b3.aoi_r0_w0 B1 ) ( read_p1_b2.aoi_r0_w0 B1 ) ++ ( read_p1_b1.aoi_r0_w0 B1 ) ( read_p1_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r1 ( sel_buf_r_p3.sel_buf_1 Y ) ( read_p2_b7.aoi_r0_w1 A1 ) ( read_p2_b6.aoi_r0_w1 A1 ) ( read_p2_b5.aoi_r0_w1 A1 ) ( read_p2_b4.aoi_r0_w1 A1 ) ( read_p2_b3.aoi_r0_w1 A1 ) ( read_p2_b2.aoi_r0_w1 A1 ) ++ ( read_p2_b1.aoi_r0_w1 A1 ) ( read_p2_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r3 ( sel_buf_r_p3.sel_buf_3 Y ) ( read_p2_b7.aoi_r0_w1 B1 ) ( read_p2_b6.aoi_r0_w1 B1 ) ( read_p2_b5.aoi_r0_w1 B1 ) ( read_p2_b4.aoi_r0_w1 B1 ) ( read_p2_b3.aoi_r0_w1 B1 ) ( read_p2_b2.aoi_r0_w1 B1 ) ++ ( read_p2_b1.aoi_r0_w1 B1 ) ( read_p2_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p4.select_r4 ( sel_buf_r_p4.sel_buf_4 Y ) ( read_p3_b7.aoi_r2_w0 A1 ) ( read_p3_b6.aoi_r2_w0 A1 ) ( read_p3_b5.aoi_r2_w0 A1 ) ( read_p3_b4.aoi_r2_w0 A1 ) ( read_p3_b3.aoi_r2_w0 A1 ) ( read_p3_b2.aoi_r2_w0 A1 ) ++ ( read_p3_b1.aoi_r2_w0 A1 ) ( read_p3_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p4.select_r6 ( sel_buf_r_p4.sel_buf_6 Y ) ( read_p3_b7.aoi_r2_w0 B1 ) ( read_p3_b6.aoi_r2_w0 B1 ) ( read_p3_b5.aoi_r2_w0 B1 ) ( read_p3_b4.aoi_r2_w0 B1 ) ( read_p3_b3.aoi_r2_w0 B1 ) ( read_p3_b2.aoi_r2_w0 B1 ) ++ ( read_p3_b1.aoi_r2_w0 B1 ) ( read_p3_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p5.select_r5 ( sel_buf_r_p5.sel_buf_5 Y ) ( read_p4_b7.aoi_r2_w1 A1 ) ( read_p4_b6.aoi_r2_w1 A1 ) ( read_p4_b5.aoi_r2_w1 A1 ) ( read_p4_b4.aoi_r2_w1 A1 ) ( read_p4_b3.aoi_r2_w1 A1 ) ( read_p4_b2.aoi_r2_w1 A1 ) ++ ( read_p4_b1.aoi_r2_w1 A1 ) ( read_p4_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p5.select_r7 ( sel_buf_r_p5.sel_buf_7 Y ) ( read_p4_b7.aoi_r2_w1 B1 ) ( read_p4_b6.aoi_r2_w1 B1 ) ( read_p4_b5.aoi_r2_w1 B1 ) ( read_p4_b4.aoi_r2_w1 B1 ) ( read_p4_b3.aoi_r2_w1 B1 ) ( read_p4_b2.aoi_r2_w1 B1 ) ++ ( read_p4_b1.aoi_r2_w1 B1 ) ( read_p4_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - read_p0_b0.t0_2 ( read_p0_b0.nand_r0_4 A ) ( read_p0_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b0.t0_4 ( read_p0_b0.nor_r0_8 A ) ( read_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b0.t2_4 ( read_p0_b0.aoi_r2_w0 Y ) ( read_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b0.t4_6 ( read_p0_b0.nand_r4_8 A ) ( read_p0_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b0.t4_8 ( read_p0_b0.nor_r0_8 B ) ( read_p0_b0.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b0.t6_8 ( read_p0_b0.aoi_r2_w1 Y ) ( read_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b1.t0_2 ( read_p0_b1.nand_r0_4 A ) ( read_p0_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b1.t0_4 ( read_p0_b1.nor_r0_8 A ) ( read_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b1.t2_4 ( read_p0_b1.aoi_r2_w0 Y ) ( read_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b1.t4_6 ( read_p0_b1.nand_r4_8 A ) ( read_p0_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b1.t4_8 ( read_p0_b1.nor_r0_8 B ) ( read_p0_b1.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b1.t6_8 ( read_p0_b1.aoi_r2_w1 Y ) ( read_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b2.t0_2 ( read_p0_b2.nand_r0_4 A ) ( read_p0_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b2.t0_4 ( read_p0_b2.nor_r0_8 A ) ( read_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b2.t2_4 ( read_p0_b2.aoi_r2_w0 Y ) ( read_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b2.t4_6 ( read_p0_b2.nand_r4_8 A ) ( read_p0_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b2.t4_8 ( read_p0_b2.nor_r0_8 B ) ( read_p0_b2.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b2.t6_8 ( read_p0_b2.aoi_r2_w1 Y ) ( read_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b3.t0_2 ( read_p0_b3.nand_r0_4 A ) ( read_p0_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b3.t0_4 ( read_p0_b3.nor_r0_8 A ) ( read_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b3.t2_4 ( read_p0_b3.aoi_r2_w0 Y ) ( read_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b3.t4_6 ( read_p0_b3.nand_r4_8 A ) ( read_p0_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b3.t4_8 ( read_p0_b3.nor_r0_8 B ) ( read_p0_b3.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b3.t6_8 ( read_p0_b3.aoi_r2_w1 Y ) ( read_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b4.t0_2 ( read_p0_b4.nand_r0_4 A ) ( read_p0_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b4.t0_4 ( read_p0_b4.nor_r0_8 A ) ( read_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b4.t2_4 ( read_p0_b4.aoi_r2_w0 Y ) ( read_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b4.t4_6 ( read_p0_b4.nand_r4_8 A ) ( read_p0_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b4.t4_8 ( read_p0_b4.nor_r0_8 B ) ( read_p0_b4.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b4.t6_8 ( read_p0_b4.aoi_r2_w1 Y ) ( read_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b5.t0_2 ( read_p0_b5.nand_r0_4 A ) ( read_p0_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b5.t0_4 ( read_p0_b5.nor_r0_8 A ) ( read_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b5.t2_4 ( read_p0_b5.aoi_r2_w0 Y ) ( read_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b5.t4_6 ( read_p0_b5.nand_r4_8 A ) ( read_p0_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b5.t4_8 ( read_p0_b5.nor_r0_8 B ) ( read_p0_b5.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b5.t6_8 ( read_p0_b5.aoi_r2_w1 Y ) ( read_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b6.t0_2 ( read_p0_b6.nand_r0_4 A ) ( read_p0_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b6.t0_4 ( read_p0_b6.nor_r0_8 A ) ( read_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b6.t2_4 ( read_p0_b6.aoi_r2_w0 Y ) ( read_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b6.t4_6 ( read_p0_b6.nand_r4_8 A ) ( read_p0_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b6.t4_8 ( read_p0_b6.nor_r0_8 B ) ( read_p0_b6.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b6.t6_8 ( read_p0_b6.aoi_r2_w1 Y ) ( read_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b7.t0_2 ( read_p0_b7.nand_r0_4 A ) ( read_p0_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b7.t0_4 ( read_p0_b7.nor_r0_8 A ) ( read_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b7.t2_4 ( read_p0_b7.aoi_r2_w0 Y ) ( read_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b7.t4_6 ( read_p0_b7.nand_r4_8 A ) ( read_p0_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b7.t4_8 ( read_p0_b7.nor_r0_8 B ) ( read_p0_b7.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b7.t6_8 ( read_p0_b7.aoi_r2_w1 Y ) ( read_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_1_0.bit0.storage ( read_p2_b0.aoi_r0_w1 A2 ) ( read_p0_b0.aoi_r0_w1 A2 ) ( storage_0_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit1.storage ( read_p2_b1.aoi_r0_w1 A2 ) ( read_p0_b1.aoi_r0_w1 A2 ) ( storage_0_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit2.storage ( read_p2_b2.aoi_r0_w1 A2 ) ( read_p0_b2.aoi_r0_w1 A2 ) ( storage_0_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit3.storage ( read_p2_b3.aoi_r0_w1 A2 ) ( read_p0_b3.aoi_r0_w1 A2 ) ( storage_0_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit4.storage ( read_p2_b4.aoi_r0_w1 A2 ) ( read_p0_b4.aoi_r0_w1 A2 ) ( storage_0_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit5.storage ( read_p2_b5.aoi_r0_w1 A2 ) ( read_p0_b5.aoi_r0_w1 A2 ) ( storage_0_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit6.storage ( read_p2_b6.aoi_r0_w1 A2 ) ( read_p0_b6.aoi_r0_w1 A2 ) ( storage_0_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit7.storage ( read_p2_b7.aoi_r0_w1 A2 ) ( read_p0_b7.aoi_r0_w1 A2 ) ( storage_0_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.gclock ( storage_0_1_0.cg GCLK ) ( storage_0_1_0.bit7.bit CLK ) ( storage_0_1_0.bit6.bit CLK ) ( storage_0_1_0.bit5.bit CLK ) ( storage_0_1_0.bit4.bit CLK ) ( storage_0_1_0.bit3.bit CLK ) ( storage_0_1_0.bit2.bit CLK ) ++ ( storage_0_1_0.bit1.bit CLK ) ( storage_0_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_1_0.we ( storage_0_1_0.gcand Y ) ( storage_0_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_p1_b0.aoi_r0_w0 B2 ) ( read_p0_b0.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_p1_b1.aoi_r0_w0 B2 ) ( read_p0_b1.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_p1_b2.aoi_r0_w0 B2 ) ( read_p0_b2.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_p1_b3.aoi_r0_w0 B2 ) ( read_p0_b3.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_p1_b4.aoi_r0_w0 B2 ) ( read_p0_b4.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_p1_b5.aoi_r0_w0 B2 ) ( read_p0_b5.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_p1_b6.aoi_r0_w0 B2 ) ( read_p0_b6.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_p1_b7.aoi_r0_w0 B2 ) ( read_p0_b7.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_1_0.bit0.storage ( storage_1_1_0.bit0.bit QN ) ( read_p2_b0.aoi_r0_w1 B2 ) ( read_p0_b0.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit1.storage ( storage_1_1_0.bit1.bit QN ) ( read_p2_b1.aoi_r0_w1 B2 ) ( read_p0_b1.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit2.storage ( storage_1_1_0.bit2.bit QN ) ( read_p2_b2.aoi_r0_w1 B2 ) ( read_p0_b2.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit3.storage ( storage_1_1_0.bit3.bit QN ) ( read_p2_b3.aoi_r0_w1 B2 ) ( read_p0_b3.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit4.storage ( storage_1_1_0.bit4.bit QN ) ( read_p2_b4.aoi_r0_w1 B2 ) ( read_p0_b4.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit5.storage ( storage_1_1_0.bit5.bit QN ) ( read_p2_b5.aoi_r0_w1 B2 ) ( read_p0_b5.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit6.storage ( storage_1_1_0.bit6.bit QN ) ( read_p2_b6.aoi_r0_w1 B2 ) ( read_p0_b6.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit7.storage ( storage_1_1_0.bit7.bit QN ) ( read_p2_b7.aoi_r0_w1 B2 ) ( read_p0_b7.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.gclock ( storage_1_1_0.cg GCLK ) ( storage_1_1_0.bit7.bit CLK ) ( storage_1_1_0.bit6.bit CLK ) ( storage_1_1_0.bit5.bit CLK ) ( storage_1_1_0.bit4.bit CLK ) ( storage_1_1_0.bit3.bit CLK ) ( storage_1_1_0.bit2.bit CLK ) ++ ( storage_1_1_0.bit1.bit CLK ) ( storage_1_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_1_0.we ( storage_1_1_0.gcand Y ) ( storage_1_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_p3_b0.aoi_r2_w0 A2 ) ( read_p0_b0.aoi_r2_w0 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_p3_b1.aoi_r2_w0 A2 ) ( read_p0_b1.aoi_r2_w0 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_p3_b2.aoi_r2_w0 A2 ) ( read_p0_b2.aoi_r2_w0 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_p3_b3.aoi_r2_w0 A2 ) ( read_p0_b3.aoi_r2_w0 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_p3_b4.aoi_r2_w0 A2 ) ( read_p0_b4.aoi_r2_w0 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_p3_b5.aoi_r2_w0 A2 ) ( read_p0_b5.aoi_r2_w0 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_p3_b6.aoi_r2_w0 A2 ) ( read_p0_b6.aoi_r2_w0 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_p3_b7.aoi_r2_w0 A2 ) ( read_p0_b7.aoi_r2_w0 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_1_0.bit0.storage ( read_p4_b0.aoi_r2_w1 A2 ) ( read_p0_b0.aoi_r2_w1 A2 ) ( storage_2_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit1.storage ( read_p4_b1.aoi_r2_w1 A2 ) ( read_p0_b1.aoi_r2_w1 A2 ) ( storage_2_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit2.storage ( read_p4_b2.aoi_r2_w1 A2 ) ( read_p0_b2.aoi_r2_w1 A2 ) ( storage_2_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit3.storage ( read_p4_b3.aoi_r2_w1 A2 ) ( read_p0_b3.aoi_r2_w1 A2 ) ( storage_2_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit4.storage ( read_p4_b4.aoi_r2_w1 A2 ) ( read_p0_b4.aoi_r2_w1 A2 ) ( storage_2_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit5.storage ( read_p4_b5.aoi_r2_w1 A2 ) ( read_p0_b5.aoi_r2_w1 A2 ) ( storage_2_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit6.storage ( read_p4_b6.aoi_r2_w1 A2 ) ( read_p0_b6.aoi_r2_w1 A2 ) ( storage_2_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit7.storage ( read_p4_b7.aoi_r2_w1 A2 ) ( read_p0_b7.aoi_r2_w1 A2 ) ( storage_2_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.gclock ( storage_2_1_0.cg GCLK ) ( storage_2_1_0.bit7.bit CLK ) ( storage_2_1_0.bit6.bit CLK ) ( storage_2_1_0.bit5.bit CLK ) ( storage_2_1_0.bit4.bit CLK ) ( storage_2_1_0.bit3.bit CLK ) ( storage_2_1_0.bit2.bit CLK ) ++ ( storage_2_1_0.bit1.bit CLK ) ( storage_2_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_1_0.we ( storage_2_1_0.gcand Y ) ( storage_2_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_p3_b0.aoi_r2_w0 B2 ) ( read_p0_b0.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_p3_b1.aoi_r2_w0 B2 ) ( read_p0_b1.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_p3_b2.aoi_r2_w0 B2 ) ( read_p0_b2.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_p3_b3.aoi_r2_w0 B2 ) ( read_p0_b3.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_p3_b4.aoi_r2_w0 B2 ) ( read_p0_b4.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_p3_b5.aoi_r2_w0 B2 ) ( read_p0_b5.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_p3_b6.aoi_r2_w0 B2 ) ( read_p0_b6.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_p3_b7.aoi_r2_w0 B2 ) ( read_p0_b7.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_1_0.bit0.storage ( storage_3_1_0.bit0.bit QN ) ( read_p4_b0.aoi_r2_w1 B2 ) ( read_p0_b0.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit1.storage ( storage_3_1_0.bit1.bit QN ) ( read_p4_b1.aoi_r2_w1 B2 ) ( read_p0_b1.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit2.storage ( storage_3_1_0.bit2.bit QN ) ( read_p4_b2.aoi_r2_w1 B2 ) ( read_p0_b2.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit3.storage ( storage_3_1_0.bit3.bit QN ) ( read_p4_b3.aoi_r2_w1 B2 ) ( read_p0_b3.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit4.storage ( storage_3_1_0.bit4.bit QN ) ( read_p4_b4.aoi_r2_w1 B2 ) ( read_p0_b4.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit5.storage ( storage_3_1_0.bit5.bit QN ) ( read_p4_b5.aoi_r2_w1 B2 ) ( read_p0_b5.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit6.storage ( storage_3_1_0.bit6.bit QN ) ( read_p4_b6.aoi_r2_w1 B2 ) ( read_p0_b6.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit7.storage ( storage_3_1_0.bit7.bit QN ) ( read_p4_b7.aoi_r2_w1 B2 ) ( read_p0_b7.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.gclock ( storage_3_1_0.cg GCLK ) ( storage_3_1_0.bit7.bit CLK ) ( storage_3_1_0.bit6.bit CLK ) ( storage_3_1_0.bit5.bit CLK ) ( storage_3_1_0.bit4.bit CLK ) ( storage_3_1_0.bit3.bit CLK ) ( storage_3_1_0.bit2.bit CLK ) ++ ( storage_3_1_0.bit1.bit CLK ) ( storage_3_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_1_0.we ( storage_3_1_0.gcand Y ) ( storage_3_1_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_0_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_1_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_2_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_3_1_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_3_1_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_1_0.gcand B ) ( storage_2_0_0.gcand B ) ( storage_1_1_0.gcand B ) ( storage_1_0_0.gcand B ) ++ ( storage_0_1_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_rb_latency_asap7.tcl b/src/ram/test/make_8x8_rb_latency_asap7.tcl +new file mode 100644 +index 0000000000..3f3a9845ef +--- /dev/null ++++ b/src/ram/test/make_8x8_rb_latency_asap7.tcl +@@ -0,0 +1,38 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees: a plain one and a banked one, an address and data per ++# bank, over 4 banks of 2 words, word 0 reading 0, their addresses ++# registered (-read_latency 1) through flops whose output is QN. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_rb_latency_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 1 \ ++ -rb_ports 1 \ ++ -read_latency 1 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -banks 4 \ ++ -bank_columns 2 \ ++ -zero_word 0 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_rb_latency_asap7.def] ++write_def $def_file ++diff_files make_8x8_rb_latency_asap7.defok $def_file ++ ++diff_files make_8x8_rb_latency_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_rb_latency_asap7_behavioral.vok b/src/ram/test/make_8x8_rb_latency_asap7_behavioral.vok +new file mode 100644 +index 0000000000..9e2e724f2b +--- /dev/null ++++ b/src/ram/test/make_8x8_rb_latency_asap7_behavioral.vok +@@ -0,0 +1,77 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q, ++ addr_w, ++ addr_r0, ++ addr_rb0_b0, ++ addr_rb0_b1, ++ addr_rb0_b2, ++ addr_rb0_b3, ++ we, ++ Qrb0_b0, ++ Qrb0_b1, ++ Qrb0_b2, ++ Qrb0_b3 ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q; ++ output reg [7:0] Qrb0_b0; ++ output reg [7:0] Qrb0_b1; ++ output reg [7:0] Qrb0_b2; ++ output reg [7:0] Qrb0_b3; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [0:0] addr_rb0_b0; ++ input [0:0] addr_rb0_b1; ++ input [0:0] addr_rb0_b2; ++ input [0:0] addr_rb0_b3; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i] && addr_w != 0) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ reg [2:0] addr_r0_q; ++ always @(posedge clk) addr_r0_q <= addr_r0; ++ reg [0:0] addr_rb0_b0_q; ++ always @(posedge clk) addr_rb0_b0_q <= addr_rb0_b0; ++ reg [0:0] addr_rb0_b1_q; ++ always @(posedge clk) addr_rb0_b1_q <= addr_rb0_b1; ++ reg [0:0] addr_rb0_b2_q; ++ always @(posedge clk) addr_rb0_b2_q <= addr_rb0_b2; ++ reg [0:0] addr_rb0_b3_q; ++ always @(posedge clk) addr_rb0_b3_q <= addr_rb0_b3; ++ ++ always @(*) begin ++ Qrb0_b0 = (0 + addr_rb0_b0_q) == 0 ? 8'd0 : mem[0 + addr_rb0_b0_q]; ++ end ++ ++ always @(*) begin ++ Qrb0_b1 = (2 + addr_rb0_b1_q) == 0 ? 8'd0 : mem[2 + addr_rb0_b1_q]; ++ end ++ ++ always @(*) begin ++ Qrb0_b2 = (4 + addr_rb0_b2_q) == 0 ? 8'd0 : mem[4 + addr_rb0_b2_q]; ++ end ++ ++ always @(*) begin ++ Qrb0_b3 = (6 + addr_rb0_b3_q) == 0 ? 8'd0 : mem[6 + addr_rb0_b3_q]; ++ end ++ ++ always @(*) begin ++ Q = addr_r0_q == 0 ? 8'd0 : mem[addr_r0_q]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index 35912fc218..2dd11c3e31 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -11,5 +11,6 @@ record_tests { + make_8x8_2r1w_reset_asap7 + make_8x8_2r1w_banks_asap7 + make_8x8_rb_asap7 ++ make_8x8_rb_latency_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 76784bb51..6cc27f69d 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -180,6 +180,7 @@ test_suite( "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_rb_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_rb_latency_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_sky130-tcl_test", ], ) diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 96a425c82..ccbe138c5 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -160,7 +160,8 @@ ASAP7 = { # on Nangate45's set/reset flop and asap7's, which stores !D; and in # banks (patch 0015), contiguous and interleaved, side by side and # stacked, tristate and AND-OR, and 12 words in banks of 3; and with a -# banked read port beside a plain one (patch 0016). +# banked read port beside a plain one (patch 0016); and with registered +# read addresses (patch 0017), on Q and QN flops. [ [ genrule( @@ -240,5 +241,8 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_banks12", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 4 -bank_order interleaved", "tb_ram_2w", 12), ("ram_rb", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 2 -bank_order interleaved -rb_ports 1", "tb_ram_rb", 8), ("ram_rb_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2 -rb_ports 1 -zero_word 0", "tb_ram_rb", 8), + ("ram_2w_latency", NANGATE45, "-storage_cell DFF_X1 -read_latency 1", "tb_ram_2w", 8), + ("ram_2w_latency_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -read_latency 1 -banks 4 -bank_columns 2 -bank_order interleaved -zero_word 0", "tb_ram_2w", 8), + ("ram_rb_latency_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -read_latency 1 -banks 4 -bank_columns 2 -rb_ports 1", "tb_ram_rb", 8), ] ] From fcef3356c09e70e5adceb4ca4504fa84f85a4bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 09:18:23 +0200 Subject: [PATCH 17/26] ram: generate_ram -write_style mux, a hold mux per bit (patch 0018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The eighth generate_regfile feature carried onto generate_ram, on 0017: -write_style mux holds each word without a clock gate, every flop on the clock and an AO22 per bit taking the new data or the flop's own value (through an inverter where the flop's output is inverted), as XiangShan's register files are built by default. clock_gate, the default, is generate_ram's clock gate per word as before. Tests: make_8x8_2r1w_mux_asap7 in generate_ram's format; the hold mux simulated on Nangate45 (tristate) and asap7 (QN flops with banks and registered reads; and with a reset), no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + patches/0018-openroad-ram-write-mux.patch | 1426 +++++++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 6 +- 4 files changed, 1435 insertions(+), 1 deletion(-) create mode 100644 patches/0018-openroad-ram-write-mux.patch diff --git a/MODULE.bazel b/MODULE.bazel index 806d2993e..7785cc770 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -153,6 +153,9 @@ archive_override( # 0017: generate_ram -read_latency 1, registered read addresses. On # 0016 (OpenROAD #11669); not upstreamed. "//patches:0017-openroad-ram-read-latency.patch", + # 0018: generate_ram -write_style mux, a hold mux per bit for the + # clock gate per word. On 0017 (OpenROAD #11669); not upstreamed. + "//patches:0018-openroad-ram-write-mux.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0018-openroad-ram-write-mux.patch b/patches/0018-openroad-ram-write-mux.patch new file mode 100644 index 000000000..b3e94976e --- /dev/null +++ b/patches/0018-openroad-ram-write-mux.patch @@ -0,0 +1,1426 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -write_style mux, a hold mux per bit + +-write_style mux holds each word without a clock gate: every flop is +on the clock, its D the new data where the word is written and its own +value elsewhere, an AO22 per bit (the AOI22 and an inverter where the +library has none) and an inverter per word for the hold; a flop whose +output is inverted feeds back through an inverter per bit. The default, +clock_gate, is generate_ram's clock gate per word, as before. Which is +better depends on the design: a clock gate per word saves a mux per +bit, a mux keeps every flop on the plain clock. Not with -use_latch. + +The eighth of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 9b6f2bbc35..3f6215e900 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -51,6 +51,7 @@ generate_ram [-mask_size bits] + [-bank_order contiguous|interleaved] + [-rb_ports count] + [-read_latency 0|1] ++ [-write_style clock_gate|mux] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -82,6 +83,7 @@ generate_ram [-mask_size bits] + | `-banks`, `-bank_columns`, `-bank_order` | The words in `banks` banks, contiguous or interleaved in the address, `bank_columns` of them side by side and the rest stacked. With banks each port decodes every word's whole address, so a bank need not be a power of two words. Not with `-column_mux_ratio` above 1 or `-use_latch`. Default: one bank. | + | `-rb_ports` | Banked read ports, with `-banks`: each an address and a data output per bank (`addr_rb_b`, `Qrb_b`), the address the word's index in its bank, every bank read independently. Default: 0. | + | `-read_latency` | `1` registers every read port's address, a plain positive-edge flop per address bit, so the data follows a cycle after the address. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. | ++| `-write_style` | How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock. Not with `-use_latch`. Default: `clock_gate`. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index fe22f91a04..1eb84cb295 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -117,7 +117,8 @@ class RamGen + int bank_columns = 1, + const std::string& bank_order = "contiguous", + int rb_ports = 0, +- int read_latency = 0); ++ int read_latency = 0, ++ const std::string& write_style = "clock_gate"); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -369,6 +370,9 @@ class RamGen + // where the flop's output is inverted the complement is the flop's and + // the inverter makes the true one. + int read_latency_{0}; ++ // -write_style mux: no clock gate; each bit's flop on the clock, its D ++ // the new data where the word is written and its own value elsewhere ++ bool write_mux_{false}; + odb::dbMaster* addr_flop_cell_{nullptr}; + std::string addr_flop_d_, addr_flop_clk_, addr_flop_q_; + bool addr_flop_inverted_{false}; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index d5521b13ab..728cf882bf 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -368,9 +368,61 @@ void RamGen::makeSlice(const int slice_idx, + select_b_nets = shared_select_b_nets; + } + +- auto gclock_net = makeNet(prefix, "gclock"); ++ // the flops' clock: the word's gated clock, or with -write_style mux ++ // the clock itself ++ auto gclock_net = write_mux_ ? clock : makeNet(prefix, "gclock"); + auto we_net = makeNet(prefix, "we"); + auto sel_cell = std::make_unique(); ++ // -write_style mux: the word's hold, where it is not written ++ dbNet* hold = nullptr; ++ if (write_mux_) { ++ hold = makeNet(prefix, "hold"); ++ makeInst(sel_cell.get(), ++ prefix, ++ "hold_inv", ++ inv_cell_, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], we_net}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], hold}}); ++ } ++ // (sel0 & a) | (sel1 & b): an AO22, or the AOI22 and an inverter where ++ // the library has no AO22 ++ auto ao22 = [&](Cell* cell, ++ const std::string& name, ++ const std::string& inst, ++ dbNet* a1, ++ dbNet* a2, ++ dbNet* b1, ++ dbNet* b2, ++ dbNet* y) { ++ if (ao22_cell_) { ++ makeInst(cell, ++ name, ++ inst, ++ ao22_cell_, ++ {{ao22_in_[0], a1}, ++ {ao22_in_[1], a2}, ++ {ao22_in_[2], b1}, ++ {ao22_in_[3], b2}, ++ {ao22_out_, y}}); ++ return; ++ } ++ auto y_b = makeNet(name, inst + "_b"); ++ makeInst(cell, ++ name, ++ inst, ++ aoi22_cell_, ++ {{aoi22_in_a1_, a1}, ++ {aoi22_in_a2_, a2}, ++ {aoi22_in_b1_, b1}, ++ {aoi22_in_b2_, b2}, ++ {aoi22_out_, y_b}}); ++ makeInst(cell, ++ name, ++ inst + "_inv", ++ inv_cell_, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], y_b}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], y}}); ++ }; + + // -reset_value: one tie per word slice holds the flops' unused pins off + dbNet* reset_off = nullptr; +@@ -440,11 +492,19 @@ void RamGen::makeSlice(const int slice_idx, + outs[r_port] = data_output[r_port][local_bit]; + } + +- dbNet* d = data_input[0][local_bit]; ++ // the written data, and the flop's D: the written data, or with ++ // -write_style mux the hold mux's output ++ dbNet* d_data = data_input[0][local_bit]; + if (num_write > 1) { +- d = makeNet(name, "d"); ++ d_data = makeNet(name, "d"); + } ++ dbNet* d = write_mux_ ? makeNet(name, "dhold") : d_data; + const int bit = start_bit_idx + local_bit; ++ dbNet* storage = and_or_read_ ? storage_nets_.at({row_idx, word_idx, bit}) ++ : nullptr; ++ if (write_mux_ && storage == nullptr) { ++ storage = makeNet(name, "storage"); ++ } + const int reset_bit + = reset_port_ ? (bit < 64 ? static_cast((reset_bits_ >> bit) & 1) + : 0) +@@ -456,10 +516,24 @@ void RamGen::makeSlice(const int slice_idx, + select_b_nets, + d, + outs, +- and_or_read_ ? storage_nets_.at({row_idx, word_idx, bit}) +- : nullptr, ++ storage, + reset_bit, + reset_off); ++ if (write_mux_) { ++ // the word's own value back where it is not written: the flop's ++ // output, through an inverter where that output is inverted ++ dbNet* old = storage; ++ if (storage_inverted_) { ++ old = makeNet(name, "q"); ++ makeInst(bit_cell.get(), ++ name, ++ "qinv", ++ inv_cell_, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], storage}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], old}}); ++ } ++ ao22(bit_cell.get(), name, "hold_mux", we_net, d_data, hold, old, d); ++ } + if (and_or_read_) { + for (const auto& node : tree_nodes_[{row_idx, word_idx, bit}]) { + makeInst(bit_cell.get(), node.prefix, node.name, node.master, node.conns); +@@ -471,7 +545,7 @@ void RamGen::makeSlice(const int slice_idx, + for (int w = 0; w < num_write; w += 2) { + const bool last = w + 2 >= num_write; + dbNet* out = last && acc == nullptr +- ? d ++ ? d_data + : makeNet(name, fmt::format("d_pair{}", w / 2)); + if (w + 1 < num_write && !ao22_cell_) { + // no AO22 in the library: the AOI22 and an inverter +@@ -512,7 +586,8 @@ void RamGen::makeSlice(const int slice_idx, + {and2_ports_[{PortRoleType::DataOut, 0}], out}}); + } + if (acc != nullptr) { +- dbNet* sum = last ? d : makeNet(name, fmt::format("d_or{}", w / 2)); ++ dbNet* sum ++ = last ? d_data : makeNet(name, fmt::format("d_or{}", w / 2)); + makeInst(bit_cell.get(), + name, + fmt::format("dor{}", w / 2), +@@ -531,14 +606,16 @@ void RamGen::makeSlice(const int slice_idx, + ram_grid_.addCell(std::move(bit_cell), bit_col); + } + +- // Make clock gate +- makeInst(sel_cell.get(), +- prefix, +- "cg", +- clock_gate_cell_, +- {{clock_gate_ports_[{PortRoleType::Clock, 0}], clock}, +- {clock_gate_ports_[{PortRoleType::DataIn, 0}], we_net}, +- {clock_gate_ports_[{PortRoleType::DataOut, 0}], gclock_net}}); ++ // Make clock gate (with -write_style mux, none: the flops hold by mux) ++ if (!write_mux_) { ++ makeInst(sel_cell.get(), ++ prefix, ++ "cg", ++ clock_gate_cell_, ++ {{clock_gate_ports_[{PortRoleType::Clock, 0}], clock}, ++ {clock_gate_ports_[{PortRoleType::DataIn, 0}], we_net}, ++ {clock_gate_ports_[{PortRoleType::DataOut, 0}], gclock_net}}); ++ } + + // Write path: this net is row_select AND with word_select so clock gate only + // fires for the addressed word within the row. Read path handled by AOI mux. +@@ -1429,12 +1506,12 @@ void RamGen::findMasters() + + // More than one write port: the write data mux, an AO22 per pair of + // ports, and an OR2 for the write enables and across pairs. ++ if ((num_write_ > 1 || write_mux_) && !ao22_cell_) { ++ // AO22 truth table: Y = A1&A2 | B1&B2 ++ ao22_cell_ = findMaster4( ++ 0xF888, "ao22", ao22_in_, ao22_out_, /*required=*/false); ++ } + if (num_write_ > 1) { +- if (!ao22_cell_) { +- // AO22 truth table: Y = A1&A2 | B1&B2 +- ao22_cell_ = findMaster4( +- 0xF888, "ao22", ao22_in_, ao22_out_, /*required=*/false); +- } + if (!or2_cell_) { + or2_cell_ = findMaster( + [](sta::LibertyPort* port) { +@@ -1798,7 +1875,8 @@ void RamGen::generate(const int mask_size, + const int bank_columns, + const std::string& bank_order, + const int rb_ports, +- const int read_latency) ++ const int read_latency, ++ const std::string& write_style) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1828,6 +1906,10 @@ void RamGen::generate(const int mask_size, + words_per_bank_ = num_words / banks_; + rb_ports_ = rb_ports; + read_latency_ = read_latency; ++ write_mux_ = write_style == "mux"; ++ if (write_mux_ && use_latch) { ++ logger_->error(RAM, 73, "-write_style mux is not supported with -use_latch."); ++ } + if (read_latency_ > 0) { + if (read_latency_ != 1) { + logger_->error(RAM, 71, "-read_latency is 0 or 1."); +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 4494870fdb..57351d4216 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -50,7 +50,8 @@ generate_ram_netlist_cmd(int mask_size, + const int bank_columns, + const char* bank_order, + const int rb_ports, +- const int read_latency) ++ const int read_latency, ++ const char* write_style) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -104,7 +105,7 @@ generate_ram_netlist_cmd(int mask_size, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, +- read_latency); ++ read_latency, write_style); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 75d6fbb387..309cad8d03 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -15,6 +15,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-bank_order contiguous|interleaved] + [-rb_ports count] + [-read_latency 0|1] ++ [-write_style clock_gate|mux] + [-zero_word word] + [-reset_value value] + [-banks count] +@@ -22,6 +23,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-bank_order contiguous|interleaved] + [-rb_ports count] + [-read_latency 0|1] ++ [-write_style clock_gate|mux] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -35,7 +37,7 @@ proc generate_ram_netlist { args } { + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports -read_latency } flags {} ++ -banks -bank_columns -bank_order -rb_ports -read_latency -write_style } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -181,6 +183,16 @@ proc generate_ram_netlist { args } { + if { [info exists keys(-bank_columns)] } { + set bank_columns $keys(-bank_columns) + } ++ # How a word holds its value between writes: a clock gate per word ++ # (clock_gate), or a mux per bit (mux). ++ set write_style clock_gate ++ if { [info exists keys(-write_style)] } { ++ set write_style $keys(-write_style) ++ if { $write_style ni {clock_gate mux} } { ++ utl::error RAM 74 "-write_style is clock_gate or mux, not $write_style." ++ } ++ } ++ + # A read latency of 1: the read addresses registered. + set read_latency 0 + if { [info exists keys(-read_latency)] } { +@@ -203,7 +215,7 @@ proc generate_ram_netlist { args } { + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ +- $rb_ports $read_latency ++ $rb_ports $read_latency $write_style + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -238,7 +250,7 @@ proc generate_ram { args } { + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports -read_latency } flags {} ++ -banks -bank_columns -bank_order -rb_ports -read_latency -write_style } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -287,7 +299,7 @@ proc generate_ram { args } { + lappend ram_netlist_args -reset_value $keys(-reset_value) + } + +- foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency} { ++ foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 83fa973277..604b8fa6be 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_2r1w_mux_asap7", + "make_8x8_rb_latency_asap7", + "make_8x8_rb_asap7", + "make_8x8_2r1w_banks_asap7", +@@ -122,6 +123,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_rb_latency_asap7_behavioral.vok", + ], ++ "make_8x8_2r1w_mux_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_mux_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_mux_asap7.defok b/src/ram/test/make_8x8_2r1w_mux_asap7.defok +new file mode 100644 +index 0000000000..b36b0af9b7 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_mux_asap7.defok +@@ -0,0 +1,943 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 2241 243 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 415 BY 1 STEP 5 0 ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 415 BY 1 STEP 5 0 ; ++COMPONENTS 409 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 216 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 237 216 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 475 216 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 712 216 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 950 216 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1188 216 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1425 216 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 1663 216 ) N ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1971 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1971 27 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1971 54 ) N ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1971 81 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1971 108 ) N ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1971 135 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1971 162 ) N ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1971 189 ) FS ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2003 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2003 27 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2003 54 ) N ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2003 81 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2003 108 ) N ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2003 135 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2003 162 ) N ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2003 189 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 2208 108 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 2208 54 ) N ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 2208 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 2057 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 2057 27 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 2057 54 ) N ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 2057 81 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 2057 108 ) N ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 2057 135 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 2057 162 ) N ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 2057 189 ) FS ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2089 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2089 27 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2089 54 ) N ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2089 81 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2089 108 ) N ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2089 135 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2089 162 ) N ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2089 189 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 2208 135 ) FS ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 2208 81 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 2208 27 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 2143 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 2143 27 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 2143 54 ) N ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 2143 81 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 2143 108 ) N ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 2143 135 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 2143 162 ) N ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 2143 189 ) FS ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2176 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2176 27 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2176 54 ) N ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2176 81 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2176 108 ) N ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2176 135 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2176 162 ) N ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2176 189 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 2224 108 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 2224 54 ) N ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 2224 0 ) N ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 172 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 410 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 410 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 410 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 410 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 410 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 410 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 410 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 648 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 648 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 648 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 648 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 648 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 648 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 885 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 885 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 885 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 885 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 885 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 885 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 885 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1123 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1123 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1123 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1123 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1123 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1123 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1123 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1360 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1360 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1360 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1360 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1360 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1360 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1360 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1598 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1598 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1598 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1598 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1598 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1598 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1598 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1836 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1836 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1836 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1836 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 205 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 205 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 205 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 205 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 194 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 194 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 194 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 442 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 442 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 442 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 442 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 432 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 432 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 432 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 680 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 680 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 680 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 680 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 669 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 669 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 669 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 918 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 918 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 918 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 918 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 907 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 907 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 907 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1155 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1155 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1155 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1155 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1393 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1393 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1393 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1393 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1382 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1630 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1630 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1630 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1630 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1620 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1620 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1620 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1868 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1857 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1857 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1857 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 2035 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 2035 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 2035 54 ) N ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 2035 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 2035 108 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 2035 135 ) FS ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 2035 162 ) N ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 2035 189 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 2122 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 2122 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 2122 54 ) N ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 2122 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 2122 108 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 2122 135 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 2122 162 ) N ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 2122 189 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1949 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1949 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1949 54 ) N ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1949 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1949 108 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1949 135 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1949 162 ) N ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1949 189 ) FS ; ++ - storage_0_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - storage_0_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 0 ) N ; ++ - storage_0_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 0 ) N ; ++ - storage_0_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 0 ) N ; ++ - storage_0_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 0 ) N ; ++ - storage_0_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - storage_0_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 0 ) N ; ++ - storage_0_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 0 ) N ; ++ - storage_0_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 0 ) N ; ++ - storage_0_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 0 ) N ; ++ - storage_0_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 0 ) N ; ++ - storage_0_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 0 ) N ; ++ - storage_0_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 0 ) N ; ++ - storage_0_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 0 ) N ; ++ - storage_0_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 0 ) N ; ++ - storage_0_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 0 ) N ; ++ - storage_0_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 0 ) N ; ++ - storage_0_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 0 ) N ; ++ - storage_0_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 0 ) N ; ++ - storage_0_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 0 ) N ; ++ - storage_0_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 0 ) N ; ++ - storage_0_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 0 ) N ; ++ - storage_0_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 0 ) N ; ++ - storage_0_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 0 ) N ; ++ - storage_0_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 0 ) N ; ++ - storage_0_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 27 ) FS ; ++ - storage_1_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 27 ) FS ; ++ - storage_1_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 27 ) FS ; ++ - storage_1_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - storage_1_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 27 ) FS ; ++ - storage_1_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 27 ) FS ; ++ - storage_1_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 27 ) FS ; ++ - storage_1_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 27 ) FS ; ++ - storage_1_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 27 ) FS ; ++ - storage_1_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 27 ) FS ; ++ - storage_1_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 27 ) FS ; ++ - storage_1_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 27 ) FS ; ++ - storage_1_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 27 ) FS ; ++ - storage_1_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 27 ) FS ; ++ - storage_1_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 27 ) FS ; ++ - storage_1_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 27 ) FS ; ++ - storage_1_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 54 ) N ; ++ - storage_2_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 54 ) N ; ++ - storage_2_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 54 ) N ; ++ - storage_2_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 54 ) N ; ++ - storage_2_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 54 ) N ; ++ - storage_2_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 54 ) N ; ++ - storage_2_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 54 ) N ; ++ - storage_2_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 54 ) N ; ++ - storage_2_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 54 ) N ; ++ - storage_2_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 54 ) N ; ++ - storage_2_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 54 ) N ; ++ - storage_2_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 54 ) N ; ++ - storage_2_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 54 ) N ; ++ - storage_2_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 54 ) N ; ++ - storage_2_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 54 ) N ; ++ - storage_2_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 54 ) N ; ++ - storage_2_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 81 ) FS ; ++ - storage_3_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 81 ) FS ; ++ - storage_3_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 81 ) FS ; ++ - storage_3_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - storage_3_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 81 ) FS ; ++ - storage_3_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 81 ) FS ; ++ - storage_3_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 81 ) FS ; ++ - storage_3_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 81 ) FS ; ++ - storage_3_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 81 ) FS ; ++ - storage_3_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 81 ) FS ; ++ - storage_3_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 81 ) FS ; ++ - storage_3_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 81 ) FS ; ++ - storage_3_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 81 ) FS ; ++ - storage_3_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 81 ) FS ; ++ - storage_3_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 81 ) FS ; ++ - storage_3_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 81 ) FS ; ++ - storage_3_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 81 ) FS ; ++ - storage_4_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 108 ) N ; ++ - storage_4_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 108 ) N ; ++ - storage_4_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 108 ) N ; ++ - storage_4_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 108 ) N ; ++ - storage_4_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 108 ) N ; ++ - storage_4_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 108 ) N ; ++ - storage_4_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 108 ) N ; ++ - storage_4_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 108 ) N ; ++ - storage_4_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 108 ) N ; ++ - storage_4_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 108 ) N ; ++ - storage_4_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 108 ) N ; ++ - storage_4_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 108 ) N ; ++ - storage_4_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 108 ) N ; ++ - storage_4_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 108 ) N ; ++ - storage_4_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 108 ) N ; ++ - storage_4_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 108 ) N ; ++ - storage_4_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 108 ) N ; ++ - storage_4_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 108 ) N ; ++ - storage_5_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 135 ) FS ; ++ - storage_5_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 135 ) FS ; ++ - storage_5_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 135 ) FS ; ++ - storage_5_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 135 ) FS ; ++ - storage_5_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 135 ) FS ; ++ - storage_5_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 135 ) FS ; ++ - storage_5_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 135 ) FS ; ++ - storage_5_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 135 ) FS ; ++ - storage_5_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 135 ) FS ; ++ - storage_5_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 135 ) FS ; ++ - storage_5_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 135 ) FS ; ++ - storage_5_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 135 ) FS ; ++ - storage_5_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 135 ) FS ; ++ - storage_5_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 135 ) FS ; ++ - storage_5_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 135 ) FS ; ++ - storage_5_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 135 ) FS ; ++ - storage_5_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 135 ) FS ; ++ - storage_5_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 135 ) FS ; ++ - storage_6_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 162 ) N ; ++ - storage_6_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 162 ) N ; ++ - storage_6_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 162 ) N ; ++ - storage_6_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 162 ) N ; ++ - storage_6_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 162 ) N ; ++ - storage_6_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 162 ) N ; ++ - storage_6_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 162 ) N ; ++ - storage_6_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 162 ) N ; ++ - storage_6_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 162 ) N ; ++ - storage_6_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 162 ) N ; ++ - storage_6_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 162 ) N ; ++ - storage_6_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 162 ) N ; ++ - storage_6_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 162 ) N ; ++ - storage_6_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 162 ) N ; ++ - storage_6_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 162 ) N ; ++ - storage_6_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 162 ) N ; ++ - storage_6_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 162 ) N ; ++ - storage_6_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 162 ) N ; ++ - storage_7_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 189 ) FS ; ++ - storage_7_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 237 189 ) FS ; ++ - storage_7_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 361 189 ) FS ; ++ - storage_7_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 345 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 475 189 ) FS ; ++ - storage_7_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 599 189 ) FS ; ++ - storage_7_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 583 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 712 189 ) FS ; ++ - storage_7_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 837 189 ) FS ; ++ - storage_7_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 820 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 950 189 ) FS ; ++ - storage_7_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1074 189 ) FS ; ++ - storage_7_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1058 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1188 189 ) FS ; ++ - storage_7_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1312 189 ) FS ; ++ - storage_7_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1296 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1425 189 ) FS ; ++ - storage_7_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1549 189 ) FS ; ++ - storage_7_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1533 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1663 189 ) FS ; ++ - storage_7_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1787 189 ) FS ; ++ - storage_7_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 1771 189 ) FS ; ++ - storage_7_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1917 189 ) FS ; ++ - storage_7_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 1900 189 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 428 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_7_0_0.bit0.hold_mux A2 ) ( storage_6_0_0.bit0.hold_mux A2 ) ( storage_5_0_0.bit0.hold_mux A2 ) ( storage_4_0_0.bit0.hold_mux A2 ) ( storage_3_0_0.bit0.hold_mux A2 ) ( storage_2_0_0.bit0.hold_mux A2 ) ++ ( storage_1_0_0.bit0.hold_mux A2 ) ( storage_0_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_7_0_0.bit1.hold_mux A2 ) ( storage_6_0_0.bit1.hold_mux A2 ) ( storage_5_0_0.bit1.hold_mux A2 ) ( storage_4_0_0.bit1.hold_mux A2 ) ( storage_3_0_0.bit1.hold_mux A2 ) ( storage_2_0_0.bit1.hold_mux A2 ) ++ ( storage_1_0_0.bit1.hold_mux A2 ) ( storage_0_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_7_0_0.bit2.hold_mux A2 ) ( storage_6_0_0.bit2.hold_mux A2 ) ( storage_5_0_0.bit2.hold_mux A2 ) ( storage_4_0_0.bit2.hold_mux A2 ) ( storage_3_0_0.bit2.hold_mux A2 ) ( storage_2_0_0.bit2.hold_mux A2 ) ++ ( storage_1_0_0.bit2.hold_mux A2 ) ( storage_0_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_7_0_0.bit3.hold_mux A2 ) ( storage_6_0_0.bit3.hold_mux A2 ) ( storage_5_0_0.bit3.hold_mux A2 ) ( storage_4_0_0.bit3.hold_mux A2 ) ( storage_3_0_0.bit3.hold_mux A2 ) ( storage_2_0_0.bit3.hold_mux A2 ) ++ ( storage_1_0_0.bit3.hold_mux A2 ) ( storage_0_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_7_0_0.bit4.hold_mux A2 ) ( storage_6_0_0.bit4.hold_mux A2 ) ( storage_5_0_0.bit4.hold_mux A2 ) ( storage_4_0_0.bit4.hold_mux A2 ) ( storage_3_0_0.bit4.hold_mux A2 ) ( storage_2_0_0.bit4.hold_mux A2 ) ++ ( storage_1_0_0.bit4.hold_mux A2 ) ( storage_0_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_7_0_0.bit5.hold_mux A2 ) ( storage_6_0_0.bit5.hold_mux A2 ) ( storage_5_0_0.bit5.hold_mux A2 ) ( storage_4_0_0.bit5.hold_mux A2 ) ( storage_3_0_0.bit5.hold_mux A2 ) ( storage_2_0_0.bit5.hold_mux A2 ) ++ ( storage_1_0_0.bit5.hold_mux A2 ) ( storage_0_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_7_0_0.bit6.hold_mux A2 ) ( storage_6_0_0.bit6.hold_mux A2 ) ( storage_5_0_0.bit6.hold_mux A2 ) ( storage_4_0_0.bit6.hold_mux A2 ) ( storage_3_0_0.bit6.hold_mux A2 ) ( storage_2_0_0.bit6.hold_mux A2 ) ++ ( storage_1_0_0.bit6.hold_mux A2 ) ( storage_0_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_7_0_0.bit7.hold_mux A2 ) ( storage_6_0_0.bit7.hold_mux A2 ) ( storage_5_0_0.bit7.hold_mux A2 ) ( storage_4_0_0.bit7.hold_mux A2 ) ( storage_3_0_0.bit7.hold_mux A2 ) ( storage_2_0_0.bit7.hold_mux A2 ) ++ ( storage_1_0_0.bit7.hold_mux A2 ) ( storage_0_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) ( storage_0_0_0.bit7.bit CLK ) ( storage_0_0_0.bit6.bit CLK ) ( storage_0_0_0.bit5.bit CLK ) ( storage_0_0_0.bit4.bit CLK ) ( storage_0_0_0.bit3.bit CLK ) ( storage_0_0_0.bit2.bit CLK ) ++ ( storage_0_0_0.bit1.bit CLK ) ( storage_0_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A1 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A1 ) ++ ( read_w0_p0_b1.aoi_r0 A1 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A1 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A1 ) ++ ( read_w0_p1_b1.aoi_r0 A1 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.dhold ( storage_0_0_0.bit0.hold_mux Y ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.q ( storage_0_0_0.bit0.hold_mux B2 ) ( storage_0_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.storage ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A2 ) ( storage_0_0_0.bit0.qinv A ) ( storage_0_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.dhold ( storage_0_0_0.bit1.hold_mux Y ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.q ( storage_0_0_0.bit1.hold_mux B2 ) ( storage_0_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.storage ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( storage_0_0_0.bit1.qinv A ) ( storage_0_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.dhold ( storage_0_0_0.bit2.hold_mux Y ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.q ( storage_0_0_0.bit2.hold_mux B2 ) ( storage_0_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.storage ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( storage_0_0_0.bit2.qinv A ) ( storage_0_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.dhold ( storage_0_0_0.bit3.hold_mux Y ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.q ( storage_0_0_0.bit3.hold_mux B2 ) ( storage_0_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.storage ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( storage_0_0_0.bit3.qinv A ) ( storage_0_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.dhold ( storage_0_0_0.bit4.hold_mux Y ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.q ( storage_0_0_0.bit4.hold_mux B2 ) ( storage_0_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.storage ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A2 ) ( storage_0_0_0.bit4.qinv A ) ( storage_0_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.dhold ( storage_0_0_0.bit5.hold_mux Y ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.q ( storage_0_0_0.bit5.hold_mux B2 ) ( storage_0_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.storage ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( storage_0_0_0.bit5.qinv A ) ( storage_0_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.dhold ( storage_0_0_0.bit6.hold_mux Y ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.q ( storage_0_0_0.bit6.hold_mux B2 ) ( storage_0_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.storage ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( storage_0_0_0.bit6.qinv A ) ( storage_0_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.dhold ( storage_0_0_0.bit7.hold_mux Y ) ( storage_0_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.q ( storage_0_0_0.bit7.hold_mux B2 ) ( storage_0_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.storage ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A2 ) ( storage_0_0_0.bit7.qinv A ) ( storage_0_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.hold ( storage_0_0_0.bit7.hold_mux B1 ) ( storage_0_0_0.bit6.hold_mux B1 ) ( storage_0_0_0.bit5.hold_mux B1 ) ( storage_0_0_0.bit4.hold_mux B1 ) ( storage_0_0_0.bit3.hold_mux B1 ) ( storage_0_0_0.bit2.hold_mux B1 ) ( storage_0_0_0.bit1.hold_mux B1 ) ++ ( storage_0_0_0.bit0.hold_mux B1 ) ( storage_0_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_0_0_0.we ( storage_0_0_0.gcand Y ) ( storage_0_0_0.bit7.hold_mux A1 ) ( storage_0_0_0.bit6.hold_mux A1 ) ( storage_0_0_0.bit5.hold_mux A1 ) ( storage_0_0_0.bit4.hold_mux A1 ) ( storage_0_0_0.bit3.hold_mux A1 ) ( storage_0_0_0.bit2.hold_mux A1 ) ++ ( storage_0_0_0.bit1.hold_mux A1 ) ( storage_0_0_0.bit0.hold_mux A1 ) ( storage_0_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.dhold ( storage_1_0_0.bit0.hold_mux Y ) ( storage_1_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.q ( storage_1_0_0.bit0.hold_mux B2 ) ( storage_1_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.qinv A ) ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.dhold ( storage_1_0_0.bit1.hold_mux Y ) ( storage_1_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.q ( storage_1_0_0.bit1.hold_mux B2 ) ( storage_1_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.qinv A ) ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.dhold ( storage_1_0_0.bit2.hold_mux Y ) ( storage_1_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.q ( storage_1_0_0.bit2.hold_mux B2 ) ( storage_1_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.qinv A ) ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.dhold ( storage_1_0_0.bit3.hold_mux Y ) ( storage_1_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.q ( storage_1_0_0.bit3.hold_mux B2 ) ( storage_1_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.qinv A ) ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.dhold ( storage_1_0_0.bit4.hold_mux Y ) ( storage_1_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.q ( storage_1_0_0.bit4.hold_mux B2 ) ( storage_1_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.qinv A ) ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.dhold ( storage_1_0_0.bit5.hold_mux Y ) ( storage_1_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.q ( storage_1_0_0.bit5.hold_mux B2 ) ( storage_1_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.qinv A ) ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.dhold ( storage_1_0_0.bit6.hold_mux Y ) ( storage_1_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.q ( storage_1_0_0.bit6.hold_mux B2 ) ( storage_1_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.qinv A ) ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.dhold ( storage_1_0_0.bit7.hold_mux Y ) ( storage_1_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.q ( storage_1_0_0.bit7.hold_mux B2 ) ( storage_1_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.qinv A ) ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.hold ( storage_1_0_0.bit7.hold_mux B1 ) ( storage_1_0_0.bit6.hold_mux B1 ) ( storage_1_0_0.bit5.hold_mux B1 ) ( storage_1_0_0.bit4.hold_mux B1 ) ( storage_1_0_0.bit3.hold_mux B1 ) ( storage_1_0_0.bit2.hold_mux B1 ) ( storage_1_0_0.bit1.hold_mux B1 ) ++ ( storage_1_0_0.bit0.hold_mux B1 ) ( storage_1_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.bit7.hold_mux A1 ) ( storage_1_0_0.bit6.hold_mux A1 ) ( storage_1_0_0.bit5.hold_mux A1 ) ( storage_1_0_0.bit4.hold_mux A1 ) ( storage_1_0_0.bit3.hold_mux A1 ) ( storage_1_0_0.bit2.hold_mux A1 ) ++ ( storage_1_0_0.bit1.hold_mux A1 ) ( storage_1_0_0.bit0.hold_mux A1 ) ( storage_1_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.dhold ( storage_2_0_0.bit0.hold_mux Y ) ( storage_2_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.q ( storage_2_0_0.bit0.hold_mux B2 ) ( storage_2_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.qinv A ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.dhold ( storage_2_0_0.bit1.hold_mux Y ) ( storage_2_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.q ( storage_2_0_0.bit1.hold_mux B2 ) ( storage_2_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.qinv A ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.dhold ( storage_2_0_0.bit2.hold_mux Y ) ( storage_2_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.q ( storage_2_0_0.bit2.hold_mux B2 ) ( storage_2_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.qinv A ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.dhold ( storage_2_0_0.bit3.hold_mux Y ) ( storage_2_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.q ( storage_2_0_0.bit3.hold_mux B2 ) ( storage_2_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.qinv A ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.dhold ( storage_2_0_0.bit4.hold_mux Y ) ( storage_2_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.q ( storage_2_0_0.bit4.hold_mux B2 ) ( storage_2_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.qinv A ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.dhold ( storage_2_0_0.bit5.hold_mux Y ) ( storage_2_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.q ( storage_2_0_0.bit5.hold_mux B2 ) ( storage_2_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.qinv A ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.dhold ( storage_2_0_0.bit6.hold_mux Y ) ( storage_2_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.q ( storage_2_0_0.bit6.hold_mux B2 ) ( storage_2_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.qinv A ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.dhold ( storage_2_0_0.bit7.hold_mux Y ) ( storage_2_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.q ( storage_2_0_0.bit7.hold_mux B2 ) ( storage_2_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.qinv A ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.hold ( storage_2_0_0.bit7.hold_mux B1 ) ( storage_2_0_0.bit6.hold_mux B1 ) ( storage_2_0_0.bit5.hold_mux B1 ) ( storage_2_0_0.bit4.hold_mux B1 ) ( storage_2_0_0.bit3.hold_mux B1 ) ( storage_2_0_0.bit2.hold_mux B1 ) ( storage_2_0_0.bit1.hold_mux B1 ) ++ ( storage_2_0_0.bit0.hold_mux B1 ) ( storage_2_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.bit7.hold_mux A1 ) ( storage_2_0_0.bit6.hold_mux A1 ) ( storage_2_0_0.bit5.hold_mux A1 ) ( storage_2_0_0.bit4.hold_mux A1 ) ( storage_2_0_0.bit3.hold_mux A1 ) ( storage_2_0_0.bit2.hold_mux A1 ) ++ ( storage_2_0_0.bit1.hold_mux A1 ) ( storage_2_0_0.bit0.hold_mux A1 ) ( storage_2_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.dhold ( storage_3_0_0.bit0.hold_mux Y ) ( storage_3_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.q ( storage_3_0_0.bit0.hold_mux B2 ) ( storage_3_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.qinv A ) ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.dhold ( storage_3_0_0.bit1.hold_mux Y ) ( storage_3_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.q ( storage_3_0_0.bit1.hold_mux B2 ) ( storage_3_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.qinv A ) ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.dhold ( storage_3_0_0.bit2.hold_mux Y ) ( storage_3_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.q ( storage_3_0_0.bit2.hold_mux B2 ) ( storage_3_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.qinv A ) ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.dhold ( storage_3_0_0.bit3.hold_mux Y ) ( storage_3_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.q ( storage_3_0_0.bit3.hold_mux B2 ) ( storage_3_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.qinv A ) ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.dhold ( storage_3_0_0.bit4.hold_mux Y ) ( storage_3_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.q ( storage_3_0_0.bit4.hold_mux B2 ) ( storage_3_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.qinv A ) ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.dhold ( storage_3_0_0.bit5.hold_mux Y ) ( storage_3_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.q ( storage_3_0_0.bit5.hold_mux B2 ) ( storage_3_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.qinv A ) ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.dhold ( storage_3_0_0.bit6.hold_mux Y ) ( storage_3_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.q ( storage_3_0_0.bit6.hold_mux B2 ) ( storage_3_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.qinv A ) ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.dhold ( storage_3_0_0.bit7.hold_mux Y ) ( storage_3_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.q ( storage_3_0_0.bit7.hold_mux B2 ) ( storage_3_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.qinv A ) ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.hold ( storage_3_0_0.bit7.hold_mux B1 ) ( storage_3_0_0.bit6.hold_mux B1 ) ( storage_3_0_0.bit5.hold_mux B1 ) ( storage_3_0_0.bit4.hold_mux B1 ) ( storage_3_0_0.bit3.hold_mux B1 ) ( storage_3_0_0.bit2.hold_mux B1 ) ( storage_3_0_0.bit1.hold_mux B1 ) ++ ( storage_3_0_0.bit0.hold_mux B1 ) ( storage_3_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.bit7.hold_mux A1 ) ( storage_3_0_0.bit6.hold_mux A1 ) ( storage_3_0_0.bit5.hold_mux A1 ) ( storage_3_0_0.bit4.hold_mux A1 ) ( storage_3_0_0.bit3.hold_mux A1 ) ( storage_3_0_0.bit2.hold_mux A1 ) ++ ( storage_3_0_0.bit1.hold_mux A1 ) ( storage_3_0_0.bit0.hold_mux A1 ) ( storage_3_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.dhold ( storage_4_0_0.bit0.hold_mux Y ) ( storage_4_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.q ( storage_4_0_0.bit0.hold_mux B2 ) ( storage_4_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.qinv A ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.dhold ( storage_4_0_0.bit1.hold_mux Y ) ( storage_4_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.q ( storage_4_0_0.bit1.hold_mux B2 ) ( storage_4_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.qinv A ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.dhold ( storage_4_0_0.bit2.hold_mux Y ) ( storage_4_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.q ( storage_4_0_0.bit2.hold_mux B2 ) ( storage_4_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.qinv A ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.dhold ( storage_4_0_0.bit3.hold_mux Y ) ( storage_4_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.q ( storage_4_0_0.bit3.hold_mux B2 ) ( storage_4_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.qinv A ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.dhold ( storage_4_0_0.bit4.hold_mux Y ) ( storage_4_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.q ( storage_4_0_0.bit4.hold_mux B2 ) ( storage_4_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.qinv A ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.dhold ( storage_4_0_0.bit5.hold_mux Y ) ( storage_4_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.q ( storage_4_0_0.bit5.hold_mux B2 ) ( storage_4_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.qinv A ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.dhold ( storage_4_0_0.bit6.hold_mux Y ) ( storage_4_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.q ( storage_4_0_0.bit6.hold_mux B2 ) ( storage_4_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.qinv A ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.dhold ( storage_4_0_0.bit7.hold_mux Y ) ( storage_4_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.q ( storage_4_0_0.bit7.hold_mux B2 ) ( storage_4_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.qinv A ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.hold ( storage_4_0_0.bit7.hold_mux B1 ) ( storage_4_0_0.bit6.hold_mux B1 ) ( storage_4_0_0.bit5.hold_mux B1 ) ( storage_4_0_0.bit4.hold_mux B1 ) ( storage_4_0_0.bit3.hold_mux B1 ) ( storage_4_0_0.bit2.hold_mux B1 ) ( storage_4_0_0.bit1.hold_mux B1 ) ++ ( storage_4_0_0.bit0.hold_mux B1 ) ( storage_4_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.gcand Y ) ( storage_4_0_0.bit7.hold_mux A1 ) ( storage_4_0_0.bit6.hold_mux A1 ) ( storage_4_0_0.bit5.hold_mux A1 ) ( storage_4_0_0.bit4.hold_mux A1 ) ( storage_4_0_0.bit3.hold_mux A1 ) ( storage_4_0_0.bit2.hold_mux A1 ) ++ ( storage_4_0_0.bit1.hold_mux A1 ) ( storage_4_0_0.bit0.hold_mux A1 ) ( storage_4_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.dhold ( storage_5_0_0.bit0.hold_mux Y ) ( storage_5_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.q ( storage_5_0_0.bit0.hold_mux B2 ) ( storage_5_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.qinv A ) ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.dhold ( storage_5_0_0.bit1.hold_mux Y ) ( storage_5_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.q ( storage_5_0_0.bit1.hold_mux B2 ) ( storage_5_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.qinv A ) ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.dhold ( storage_5_0_0.bit2.hold_mux Y ) ( storage_5_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.q ( storage_5_0_0.bit2.hold_mux B2 ) ( storage_5_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.qinv A ) ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.dhold ( storage_5_0_0.bit3.hold_mux Y ) ( storage_5_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.q ( storage_5_0_0.bit3.hold_mux B2 ) ( storage_5_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.qinv A ) ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.dhold ( storage_5_0_0.bit4.hold_mux Y ) ( storage_5_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.q ( storage_5_0_0.bit4.hold_mux B2 ) ( storage_5_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.qinv A ) ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.dhold ( storage_5_0_0.bit5.hold_mux Y ) ( storage_5_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.q ( storage_5_0_0.bit5.hold_mux B2 ) ( storage_5_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.qinv A ) ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.dhold ( storage_5_0_0.bit6.hold_mux Y ) ( storage_5_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.q ( storage_5_0_0.bit6.hold_mux B2 ) ( storage_5_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.qinv A ) ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.dhold ( storage_5_0_0.bit7.hold_mux Y ) ( storage_5_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.q ( storage_5_0_0.bit7.hold_mux B2 ) ( storage_5_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.qinv A ) ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.hold ( storage_5_0_0.bit7.hold_mux B1 ) ( storage_5_0_0.bit6.hold_mux B1 ) ( storage_5_0_0.bit5.hold_mux B1 ) ( storage_5_0_0.bit4.hold_mux B1 ) ( storage_5_0_0.bit3.hold_mux B1 ) ( storage_5_0_0.bit2.hold_mux B1 ) ( storage_5_0_0.bit1.hold_mux B1 ) ++ ( storage_5_0_0.bit0.hold_mux B1 ) ( storage_5_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.gcand Y ) ( storage_5_0_0.bit7.hold_mux A1 ) ( storage_5_0_0.bit6.hold_mux A1 ) ( storage_5_0_0.bit5.hold_mux A1 ) ( storage_5_0_0.bit4.hold_mux A1 ) ( storage_5_0_0.bit3.hold_mux A1 ) ( storage_5_0_0.bit2.hold_mux A1 ) ++ ( storage_5_0_0.bit1.hold_mux A1 ) ( storage_5_0_0.bit0.hold_mux A1 ) ( storage_5_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.dhold ( storage_6_0_0.bit0.hold_mux Y ) ( storage_6_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.q ( storage_6_0_0.bit0.hold_mux B2 ) ( storage_6_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.qinv A ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.dhold ( storage_6_0_0.bit1.hold_mux Y ) ( storage_6_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.q ( storage_6_0_0.bit1.hold_mux B2 ) ( storage_6_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.qinv A ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.dhold ( storage_6_0_0.bit2.hold_mux Y ) ( storage_6_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.q ( storage_6_0_0.bit2.hold_mux B2 ) ( storage_6_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.qinv A ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.dhold ( storage_6_0_0.bit3.hold_mux Y ) ( storage_6_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.q ( storage_6_0_0.bit3.hold_mux B2 ) ( storage_6_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.qinv A ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.dhold ( storage_6_0_0.bit4.hold_mux Y ) ( storage_6_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.q ( storage_6_0_0.bit4.hold_mux B2 ) ( storage_6_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.qinv A ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.dhold ( storage_6_0_0.bit5.hold_mux Y ) ( storage_6_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.q ( storage_6_0_0.bit5.hold_mux B2 ) ( storage_6_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.qinv A ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.dhold ( storage_6_0_0.bit6.hold_mux Y ) ( storage_6_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.q ( storage_6_0_0.bit6.hold_mux B2 ) ( storage_6_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.qinv A ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.dhold ( storage_6_0_0.bit7.hold_mux Y ) ( storage_6_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.q ( storage_6_0_0.bit7.hold_mux B2 ) ( storage_6_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.qinv A ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.hold ( storage_6_0_0.bit7.hold_mux B1 ) ( storage_6_0_0.bit6.hold_mux B1 ) ( storage_6_0_0.bit5.hold_mux B1 ) ( storage_6_0_0.bit4.hold_mux B1 ) ( storage_6_0_0.bit3.hold_mux B1 ) ( storage_6_0_0.bit2.hold_mux B1 ) ( storage_6_0_0.bit1.hold_mux B1 ) ++ ( storage_6_0_0.bit0.hold_mux B1 ) ( storage_6_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.gcand Y ) ( storage_6_0_0.bit7.hold_mux A1 ) ( storage_6_0_0.bit6.hold_mux A1 ) ( storage_6_0_0.bit5.hold_mux A1 ) ( storage_6_0_0.bit4.hold_mux A1 ) ( storage_6_0_0.bit3.hold_mux A1 ) ( storage_6_0_0.bit2.hold_mux A1 ) ++ ( storage_6_0_0.bit1.hold_mux A1 ) ( storage_6_0_0.bit0.hold_mux A1 ) ( storage_6_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.dhold ( storage_7_0_0.bit0.hold_mux Y ) ( storage_7_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.q ( storage_7_0_0.bit0.hold_mux B2 ) ( storage_7_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.qinv A ) ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.dhold ( storage_7_0_0.bit1.hold_mux Y ) ( storage_7_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.q ( storage_7_0_0.bit1.hold_mux B2 ) ( storage_7_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.qinv A ) ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.dhold ( storage_7_0_0.bit2.hold_mux Y ) ( storage_7_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.q ( storage_7_0_0.bit2.hold_mux B2 ) ( storage_7_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.qinv A ) ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.dhold ( storage_7_0_0.bit3.hold_mux Y ) ( storage_7_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.q ( storage_7_0_0.bit3.hold_mux B2 ) ( storage_7_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.qinv A ) ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.dhold ( storage_7_0_0.bit4.hold_mux Y ) ( storage_7_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.q ( storage_7_0_0.bit4.hold_mux B2 ) ( storage_7_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.qinv A ) ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.dhold ( storage_7_0_0.bit5.hold_mux Y ) ( storage_7_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.q ( storage_7_0_0.bit5.hold_mux B2 ) ( storage_7_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.qinv A ) ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.dhold ( storage_7_0_0.bit6.hold_mux Y ) ( storage_7_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.q ( storage_7_0_0.bit6.hold_mux B2 ) ( storage_7_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.qinv A ) ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.dhold ( storage_7_0_0.bit7.hold_mux Y ) ( storage_7_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.q ( storage_7_0_0.bit7.hold_mux B2 ) ( storage_7_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.qinv A ) ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.hold ( storage_7_0_0.bit7.hold_mux B1 ) ( storage_7_0_0.bit6.hold_mux B1 ) ( storage_7_0_0.bit5.hold_mux B1 ) ( storage_7_0_0.bit4.hold_mux B1 ) ( storage_7_0_0.bit3.hold_mux B1 ) ( storage_7_0_0.bit2.hold_mux B1 ) ( storage_7_0_0.bit1.hold_mux B1 ) ++ ( storage_7_0_0.bit0.hold_mux B1 ) ( storage_7_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.gcand Y ) ( storage_7_0_0.bit7.hold_mux A1 ) ( storage_7_0_0.bit6.hold_mux A1 ) ( storage_7_0_0.bit5.hold_mux A1 ) ( storage_7_0_0.bit4.hold_mux A1 ) ( storage_7_0_0.bit3.hold_mux A1 ) ( storage_7_0_0.bit2.hold_mux A1 ) ++ ( storage_7_0_0.bit1.hold_mux A1 ) ( storage_7_0_0.bit0.hold_mux A1 ) ( storage_7_0_0.hold_inv A ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) ( storage_0_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_7_0_0.gcand B ) ( storage_6_0_0.gcand B ) ( storage_5_0_0.gcand B ) ( storage_4_0_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_0_0.gcand B ) ++ ( storage_1_0_0.gcand B ) ( storage_0_0_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_mux_asap7.tcl b/src/ram/test/make_8x8_2r1w_mux_asap7.tcl +new file mode 100644 +index 0000000000..09db3e2c83 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_mux_asap7.tcl +@@ -0,0 +1,33 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees, and each word holds by a mux per bit, its QN flop fed ++# back through an inverter (-write_style mux). ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_mux_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -write_style mux \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_mux_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_mux_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_mux_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_mux_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_mux_asap7_behavioral.vok +new file mode 100644 +index 0000000000..a5a0666525 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_mux_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i]) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index 2dd11c3e31..2876c040c3 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -12,5 +12,6 @@ record_tests { + make_8x8_2r1w_banks_asap7 + make_8x8_rb_asap7 + make_8x8_rb_latency_asap7 ++ make_8x8_2r1w_mux_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 6cc27f69d..1da211479 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -176,6 +176,7 @@ test_suite( "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_and_or_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_banks_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_mux_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_reset_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index ccbe138c5..ff3aff04f 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -161,7 +161,8 @@ ASAP7 = { # banks (patch 0015), contiguous and interleaved, side by side and # stacked, tristate and AND-OR, and 12 words in banks of 3; and with a # banked read port beside a plain one (patch 0016); and with registered -# read addresses (patch 0017), on Q and QN flops. +# read addresses (patch 0017), on Q and QN flops; and holding words by a +# mux per bit instead of a clock gate (patch 0018). [ [ genrule( @@ -244,5 +245,8 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_latency", NANGATE45, "-storage_cell DFF_X1 -read_latency 1", "tb_ram_2w", 8), ("ram_2w_latency_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -read_latency 1 -banks 4 -bank_columns 2 -bank_order interleaved -zero_word 0", "tb_ram_2w", 8), ("ram_rb_latency_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -read_latency 1 -banks 4 -bank_columns 2 -rb_ports 1", "tb_ram_rb", 8), + ("ram_2w_mux", NANGATE45, "-storage_cell DFF_X1 -write_style mux", "tb_ram_2w", 8), + ("ram_2w_mux_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -read_latency 1", "tb_ram_2w", 8), + ("ram_2w_rst_mux_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -write_style mux -reset_value 0xa5", "tb_ram_2w_rst", 8), ] ] From 48e4168988cc201bbf687145028848dd1b157844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 09:24:56 +0200 Subject: [PATCH 18/26] ram: generate_ram_netlist -periphery unplaced (patch 0019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ninth generate_regfile feature carried onto generate_ram, on 0018: generate_regfile's mode netlist. -periphery unplaced leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for the parent to place, size and buffer; the outline is the placed core and a row; each pin sits where its connections land, on -pin_layer's tracks, for a macro placer before the parent dissolves the core. The same cut that took riscv32i's register file abstract from 996 to 673 um2. Tests: make_8x8_2r1w_unplaced_asap7 in generate_ram's format (176 cells placed inside the outline, 105 unplaced, 35 pins inside); the netlist simulated with its periphery unplaced, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 4 + ...0019-openroad-ram-periphery-unplaced.patch | 1309 +++++++++++++++++ test/regfile/BUILD.bazel | 1 + test/regfile/sim/BUILD.bazel | 4 +- 4 files changed, 1317 insertions(+), 1 deletion(-) create mode 100644 patches/0019-openroad-ram-periphery-unplaced.patch diff --git a/MODULE.bazel b/MODULE.bazel index 7785cc770..2a3680047 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -156,6 +156,10 @@ archive_override( # 0018: generate_ram -write_style mux, a hold mux per bit for the # clock gate per word. On 0017 (OpenROAD #11669); not upstreamed. "//patches:0018-openroad-ram-write-mux.patch", + # 0019: generate_ram_netlist -periphery unplaced, the core alone + # placed and outlined, for a parent to dissolve. On 0018 (OpenROAD + # #11669); not upstreamed. + "//patches:0019-openroad-ram-periphery-unplaced.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0019-openroad-ram-periphery-unplaced.patch b/patches/0019-openroad-ram-periphery-unplaced.patch new file mode 100644 index 000000000..4dc5922a8 --- /dev/null +++ b/patches/0019-openroad-ram-periphery-unplaced.patch @@ -0,0 +1,1309 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram_netlist -periphery unplaced + +-periphery unplaced leaves the periphery (address inverters and +registers, decoders, select buffers, each word's select cell and the +input buffers) for a parent to place, size and buffer: the parent alone +knows the drivers and loads outside the array. The outline is cut to +what stays placed, the core, and a row above it for a parent of the +other row parity, so a parent sizing its floorplan by utilization +charges the core and nothing else. Each pin goes where its connections +land, on -pin_layer's track grid inside the outline, for a macro +placer to orient the core by before the parent dissolves it into its +own rows. generate_ram_netlist only; generate_ram's flow places +everything. + +The ninth of the generate_regfile features carried onto generate_ram +(its mode netlist); see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 3f6215e900..918957177a 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -84,6 +84,7 @@ generate_ram [-mask_size bits] + | `-rb_ports` | Banked read ports, with `-banks`: each an address and a data output per bank (`addr_rb_b`, `Qrb_b`), the address the word's index in its bank, every bank read independently. Default: 0. | + | `-read_latency` | `1` registers every read port's address, a plain positive-edge flop per address bit, so the data follows a cycle after the address. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. | + | `-write_style` | How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock. Not with `-use_latch`. Default: `clock_gate`. | ++| `-periphery`, `-pin_layer` | `generate_ram_netlist` only. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. Default: `placed`. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 1eb84cb295..f751f6c63d 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -118,7 +118,9 @@ class RamGen + const std::string& bank_order = "contiguous", + int rb_ports = 0, + int read_latency = 0, +- const std::string& write_style = "clock_gate"); ++ const std::string& write_style = "clock_gate", ++ const std::string& periphery = "placed", ++ const std::string& pin_layer = ""); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -373,6 +375,16 @@ class RamGen + // -write_style mux: no clock gate; each bit's flop on the clock, its D + // the new data where the word is written and its own value elsewhere + bool write_mux_{false}; ++ // -periphery unplaced: the periphery (address inverters and registers, ++ // decoders, select buffers, each word's select cell, the input ++ // buffers) left for a parent to place; the outline the placed core and ++ // a row; each pin where its connections land, on pin_layer_'s tracks ++ bool periphery_unplaced_{false}; ++ std::string pin_layer_; ++ bool marking_periphery_{false}; ++ Cell* periphery_cell_{nullptr}; ++ std::vector periphery_insts_; ++ void unplacePeriphery(); + odb::dbMaster* addr_flop_cell_{nullptr}; + std::string addr_flop_d_, addr_flop_clk_, addr_flop_q_; + bool addr_flop_inverted_{false}; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 728cf882bf..4cdfe57e2c 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -81,6 +81,9 @@ dbInst* RamGen::makeInst( + { + const auto inst_name = fmt::format("{}.{}", prefix, name); + auto inst = dbInst::create(block_, master, inst_name.c_str()); ++ if (marking_periphery_ || (cell && cell == periphery_cell_)) { ++ periphery_insts_.push_back(inst); ++ } + for (auto& [mterm_name, net] : connections) { + auto mterm = master->findMTerm(mterm_name.c_str()); + if (!mterm) { +@@ -373,6 +376,7 @@ void RamGen::makeSlice(const int slice_idx, + auto gclock_net = write_mux_ ? clock : makeNet(prefix, "gclock"); + auto we_net = makeNet(prefix, "we"); + auto sel_cell = std::make_unique(); ++ periphery_cell_ = sel_cell.get(); // each word's select cell + // -write_style mux: the word's hold, where it is not written + dbNet* hold = nullptr; + if (write_mux_) { +@@ -749,6 +753,7 @@ void RamGen::makeDecoderColumn( + const std::vector& decoder_output_nets) + { + auto decoder_layout = std::make_unique(odb::vertical); ++ marking_periphery_ = true; + + const int layers = std::ceil(std::log2(num_rows)) - 1; + +@@ -784,6 +789,7 @@ void RamGen::makeDecoderColumn( + } + decoder_layout->addCell(std::move(word_cell)); + } ++ marking_periphery_ = false; + ram_grid_.addLayout(std::move(decoder_layout)); + } + +@@ -794,6 +800,7 @@ void RamGen::makeBufferColumn(const std::string& prefix, + const int words_per_row) + { + auto buffer_layout = std::make_unique(odb::vertical); ++ marking_periphery_ = true; + for (int row = 0; row < num_rows; ++row) { + auto buf_cell = std::make_unique(); + // a buffer per select: one per row, or with banks one per word +@@ -812,6 +819,7 @@ void RamGen::makeBufferColumn(const std::string& prefix, + } + buffer_layout->addCell(std::move(buf_cell)); + } ++ marking_periphery_ = false; + ram_grid_.addLayout(std::move(buffer_layout)); + } + +@@ -823,6 +831,7 @@ void RamGen::makeWordDecoderColumn( + const std::vector& decoder_output_nets) + { + auto decoder_layout = std::make_unique(odb::vertical); ++ marking_periphery_ = true; + for (int row = 0; row < num_rows; ++row) { + auto row_cell = std::make_unique(); + for (int k = 0; k < words_per_row; ++k) { +@@ -867,6 +876,7 @@ void RamGen::makeWordDecoderColumn( + } + decoder_layout->addCell(std::move(row_cell)); + } ++ marking_periphery_ = false; + ram_grid_.addLayout(std::move(decoder_layout)); + } + +@@ -880,6 +890,7 @@ std::unique_ptr RamGen::makeInverterColumn( + { + auto cell_inv_layout = std::make_unique(odb::vertical); + int ports_in_col = end_port - start_port; ++ marking_periphery_ = true; + + // number of inverters per bit group (one per port in this column) + // fillers evenly space each bit group within the column +@@ -927,6 +938,7 @@ std::unique_ptr RamGen::makeInverterColumn( + } + } + ++ marking_periphery_ = false; + // pad any remaining rows + int total_placed = (ports_in_col + fillers_per_group) * num_row_bits; + for (int f = total_placed; f < num_rows; ++f) { +@@ -1876,7 +1888,9 @@ void RamGen::generate(const int mask_size, + const std::string& bank_order, + const int rb_ports, + const int read_latency, +- const std::string& write_style) ++ const std::string& write_style, ++ const std::string& periphery, ++ const std::string& pin_layer) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1907,6 +1921,11 @@ void RamGen::generate(const int mask_size, + rb_ports_ = rb_ports; + read_latency_ = read_latency; + write_mux_ = write_style == "mux"; ++ periphery_unplaced_ = periphery == "unplaced"; ++ pin_layer_ = pin_layer; ++ periphery_insts_.clear(); ++ marking_periphery_ = false; ++ periphery_cell_ = nullptr; + if (write_mux_ && use_latch) { + logger_->error(RAM, 73, "-write_style mux is not supported with -use_latch."); + } +@@ -2677,6 +2696,7 @@ void RamGen::generate(const int mask_size, + for (int bit = 0; bit < mask_size; ++bit) { + int bit_idx = bit + slice * mask_size; + auto buffer_grid_cell = std::make_unique(); ++ marking_periphery_ = true; // the input buffers + for (int w = 0; w < num_write; ++w) { + makeInst(buffer_grid_cell.get(), + num_write == 1 ? "buffer" : fmt::format("buffer{}", w), +@@ -2687,6 +2707,7 @@ void RamGen::generate(const int mask_size, + {buffer_ports_[{PortRoleType::DataOut, 0}], + D_nets[w][bit_idx]}}); + } ++ marking_periphery_ = false; + int buf_col = slice * (mask_size * column_mux_ratio + column_mux_ratio) + + bit * column_mux_ratio; + ram_grid_.addCell(std::move(buffer_grid_cell), buf_col); +@@ -2945,6 +2966,10 @@ void RamGen::generate(const int mask_size, + + block_->setDieArea(odb::Rect(0, 0, max_x_coord, max_y_coord)); + block_->setCoreArea(block_->computeCoreArea()); ++ periphery_cell_ = nullptr; ++ if (periphery_unplaced_) { ++ unplacePeriphery(); ++ } + + writeBehavioralVerilog(behavioral_verilog_filename_, + slices_per_word, +@@ -2955,6 +2980,125 @@ void RamGen::generate(const int mask_size, + w_ports); + } + ++// -periphery unplaced: the periphery left for a parent to place and the ++// outline cut to what stays, the placed core, so a parent sizing its ++// floorplan by utilization charges the core and nothing else. Each pin ++// goes where its connections land, the centroid of the cells on its net ++// (those of the periphery too, while they are still placed), on the pin ++// layer's track grid inside the outline: these pins are for a macro ++// placer to orient the core by, never routed. ++void RamGen::unplacePeriphery() ++{ ++ odb::dbTechLayer* layer ++ = db_->getTech()->findLayer(pin_layer_.c_str()); ++ if (layer == nullptr) { ++ logger_->error(RAM, ++ 75, ++ "-periphery unplaced needs -pin_layer, a routing layer; " ++ "{} is not one.", ++ pin_layer_); ++ } ++ // the pins' centres, before anything moves ++ std::vector> pins; ++ for (dbBTerm* term : block_->getBTerms()) { ++ dbNet* net = term->getNet(); ++ if (net == nullptr) { ++ continue; ++ } ++ int64_t sx = 0; ++ int64_t sy = 0; ++ int n = 0; ++ for (odb::dbITerm* it : net->getITerms()) { ++ const odb::Rect b = it->getInst()->getBBox()->getBox(); ++ sx += b.xCenter(); ++ sy += b.yCenter(); ++ ++n; ++ } ++ if (n > 0) { ++ pins.emplace_back(term, odb::Point(sx / n, sy / n)); ++ } ++ } ++ for (odb::dbInst* inst : periphery_insts_) { ++ inst->setPlacementStatus(odb::dbPlacementStatus::UNPLACED); ++ } ++ // the placed core's bounding box, and a row above it: a parent whose ++ // rows are of the other parity there moves the core up a row ++ odb::Rect core; ++ core.mergeInit(); ++ for (odb::dbInst* inst : block_->getInsts()) { ++ if (inst->getPlacementStatus().isPlaced()) { ++ core.merge(inst->getBBox()->getBox()); ++ } ++ } ++ odb::dbRow* first = *block_->getRows().begin(); ++ const int row_h = first->getBBox().dy(); ++ odb::dbSite* site = first->getSite(); ++ const int site_w = site->getWidth(); ++ const int dx = core.xMin(); ++ const int dy = core.yMin(); ++ const int first_row = dy / row_h; ++ const int num_rows = core.dy() / row_h + 1; ++ const int width = core.dx(); ++ const int height = num_rows * row_h; ++ for (odb::dbInst* inst : block_->getInsts()) { ++ if (inst->getPlacementStatus().isPlaced()) { ++ const odb::Point at = inst->getLocation(); ++ const odb::dbPlacementStatus status = inst->getPlacementStatus(); ++ // a FIRM cell's origin is fixed (ODB-0359) ++ inst->setPlacementStatus(odb::dbPlacementStatus::PLACED); ++ inst->setLocation(at.x() - dx, at.y() - dy); ++ inst->setPlacementStatus(status); ++ } ++ } ++ std::vector rows(block_->getRows().begin(), ++ block_->getRows().end()); ++ for (odb::dbRow* row : rows) { ++ odb::dbRow::destroy(row); ++ } ++ for (int r = 0; r < num_rows; ++r) { ++ dbRow::create(block_, ++ fmt::format("RAM_ROW{}", r).c_str(), ++ site, ++ 0, ++ r * row_h, ++ (first_row + r) % 2 == 0 ? odb::dbOrientType::R0 ++ : odb::dbOrientType::MX, ++ odb::dbRowDir::HORIZONTAL, ++ width / site_w, ++ site_w); ++ } ++ block_->setDieArea(odb::Rect(0, 0, width, height)); ++ block_->setCoreArea(block_->computeCoreArea()); ++ // each pin on the layer's track grid, inside the outline ++ const int pitch = std::max(1, static_cast(layer->getPitch())); ++ const int offset = layer->getOffset(); ++ const int half = std::max(1, static_cast(layer->getWidth()) / 2); ++ auto on_track = [&](int v, int hi) { ++ int t = offset + std::max(0, (v - offset + pitch / 2) / pitch) * pitch; ++ while (t > hi - half && t - pitch >= half) { ++ t -= pitch; ++ } ++ while (t < half) { ++ t += pitch; ++ } ++ return t; ++ }; ++ for (auto& [term, at] : pins) { ++ const int x = on_track(at.x() - dx, width); ++ const int y = on_track(at.y() - dy, height); ++ odb::dbBPin* pin = odb::dbBPin::create(term); ++ odb::dbBox::create(pin, layer, x - half, y - half, x + half, y + half); ++ pin->setPlacementStatus(odb::dbPlacementStatus::FIRM); ++ } ++ logger_->info(RAM, ++ 76, ++ "-periphery unplaced: {} periphery instances left unplaced; " ++ "the core is {:.3f} x {:.3f} um.", ++ periphery_insts_.size(), ++ block_->dbuToMicrons(width), ++ block_->dbuToMicrons(height)); ++} ++ + void RamGen::setBehavioralVerilogFilename(const std::string& filename) + { + behavioral_verilog_filename_ = filename; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 57351d4216..1d62729854 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -51,7 +51,9 @@ generate_ram_netlist_cmd(int mask_size, + const char* bank_order, + const int rb_ports, + const int read_latency, +- const char* write_style) ++ const char* write_style, ++ const char* periphery, ++ const char* pin_layer) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -105,7 +107,7 @@ generate_ram_netlist_cmd(int mask_size, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, +- read_latency, write_style); ++ read_latency, write_style, periphery, pin_layer); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 309cad8d03..7ae7eb7754 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -24,6 +24,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] ++ [-periphery placed|unplaced] ++ [-pin_layer layer] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -37,7 +39,8 @@ proc generate_ram_netlist { args } { + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports -read_latency -write_style } flags {} ++ -banks -bank_columns -bank_order -rb_ports -read_latency -write_style ++ -periphery -pin_layer } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -183,6 +186,21 @@ proc generate_ram_netlist { args } { + if { [info exists keys(-bank_columns)] } { + set bank_columns $keys(-bank_columns) + } ++ # The periphery placed with the array (placed), or left for a parent to ++ # place, the outline then the core alone and the pins on -pin_layer ++ # where their connections land (unplaced). ++ set periphery placed ++ if { [info exists keys(-periphery)] } { ++ set periphery $keys(-periphery) ++ if { $periphery ni {placed unplaced} } { ++ utl::error RAM 77 "-periphery is placed or unplaced, not $periphery." ++ } ++ } ++ set pin_layer "" ++ if { [info exists keys(-pin_layer)] } { ++ set pin_layer $keys(-pin_layer) ++ } ++ + # How a word holds its value between writes: a clock gate per word + # (clock_gate), or a mux per bit (mux). + set write_style clock_gate +@@ -215,7 +233,7 @@ proc generate_ram_netlist { args } { + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ +- $rb_ports $read_latency $write_style ++ $rb_ports $read_latency $write_style $periphery $pin_layer + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 604b8fa6be..eab9e82099 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ + ] + + PASSFAIL_TESTS = [ ++ "make_8x8_2r1w_unplaced_asap7", + "make_8x8_2r1w_mux_asap7", + "make_8x8_rb_latency_asap7", + "make_8x8_rb_asap7", +@@ -128,6 +129,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_mux_asap7_behavioral.vok", + ], ++ "make_8x8_2r1w_unplaced_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_unplaced_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_unplaced_asap7.defok b/src/ram/test/make_8x8_2r1w_unplaced_asap7.defok +new file mode 100644 +index 0000000000..2df2030d7f +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_unplaced_asap7.defok +@@ -0,0 +1,777 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 1382 243 ) ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 256 BY 1 STEP 5 0 ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 256 BY 1 STEP 5 0 ; ++COMPONENTS 281 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + UNPLACED ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + UNPLACED ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 108 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 108 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 108 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 280 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 280 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 280 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 280 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 453 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 453 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 453 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 626 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 626 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 626 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 626 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 799 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 799 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 799 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 799 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 972 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 972 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 972 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 972 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 972 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1317 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 140 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 140 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 129 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 129 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 129 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 313 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 313 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 313 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 302 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 302 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 302 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 486 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 486 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 475 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 658 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 658 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 658 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 648 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 648 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 831 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 831 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 831 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 820 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 993 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 993 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 993 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1166 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1339 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + UNPLACED ; ++ - storage_0_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - storage_0_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - storage_0_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - storage_0_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - storage_0_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - storage_0_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - storage_0_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - storage_0_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - storage_0_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_0_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_4_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 108 ) N ; ++ - storage_4_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_4_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_5_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 135 ) FS ; ++ - storage_5_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_5_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_6_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 162 ) N ; ++ - storage_6_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_6_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++ - storage_7_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 189 ) FS ; ++ - storage_7_0_0.cg ICGx1_ASAP7_75t_R + UNPLACED ; ++ - storage_7_0_0.gcand AND2x2_ASAP7_75t_R + UNPLACED ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 9 230 ) N ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 182 230 ) N ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 355 230 ) N ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 528 230 ) N ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 700 230 ) N ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 873 230 ) N ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 1046 230 ) N ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 1219 230 ) N ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 120 96 ) N ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 292 96 ) N ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 465 96 ) N ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 638 96 ) N ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 811 96 ) N ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 984 96 ) N ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1156 96 ) N ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1329 96 ) N ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 139 96 ) N ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 312 96 ) N ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 484 96 ) N ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 657 96 ) N ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 830 96 ) N ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 1003 96 ) N ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 1 1 ) ++ + FIXED ( 1176 96 ) N ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1348 96 ) N ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 2 ) ++ + FIXED ( 1377 124 ) N ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 2 ) ++ + FIXED ( 1377 124 ) N ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 139 ) N ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 120 ) N ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 120 ) N ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 134 ) N ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 120 ) N ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 120 ) N ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 1 ) ++ + FIXED ( 1377 134 ) N ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 2 ) ++ + FIXED ( 1377 105 ) N ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ++ + PORT ++ + LAYER M4 ( -1 -1 ) ( 2 2 ) ++ + FIXED ( 1377 105 ) N ; ++END PINS ++NETS 300 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_7_0_0.bit0.bit D ) ( storage_6_0_0.bit0.bit D ) ( storage_5_0_0.bit0.bit D ) ( storage_4_0_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ++ ( storage_1_0_0.bit0.bit D ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_7_0_0.bit1.bit D ) ( storage_6_0_0.bit1.bit D ) ( storage_5_0_0.bit1.bit D ) ( storage_4_0_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ++ ( storage_1_0_0.bit1.bit D ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_7_0_0.bit2.bit D ) ( storage_6_0_0.bit2.bit D ) ( storage_5_0_0.bit2.bit D ) ( storage_4_0_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ++ ( storage_1_0_0.bit2.bit D ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_7_0_0.bit3.bit D ) ( storage_6_0_0.bit3.bit D ) ( storage_5_0_0.bit3.bit D ) ( storage_4_0_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ++ ( storage_1_0_0.bit3.bit D ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_7_0_0.bit4.bit D ) ( storage_6_0_0.bit4.bit D ) ( storage_5_0_0.bit4.bit D ) ( storage_4_0_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ++ ( storage_1_0_0.bit4.bit D ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_7_0_0.bit5.bit D ) ( storage_6_0_0.bit5.bit D ) ( storage_5_0_0.bit5.bit D ) ( storage_4_0_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ++ ( storage_1_0_0.bit5.bit D ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_7_0_0.bit6.bit D ) ( storage_6_0_0.bit6.bit D ) ( storage_5_0_0.bit6.bit D ) ( storage_4_0_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ++ ( storage_1_0_0.bit6.bit D ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_7_0_0.bit7.bit D ) ( storage_6_0_0.bit7.bit D ) ( storage_5_0_0.bit7.bit D ) ( storage_4_0_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ++ ( storage_1_0_0.bit7.bit D ) ( storage_0_0_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.cg CLK ) ( storage_6_0_0.cg CLK ) ( storage_5_0_0.cg CLK ) ( storage_4_0_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_0_0.cg CLK ) ++ ( storage_1_0_0.cg CLK ) ( storage_0_0_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A1 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A1 ) ++ ( read_w0_p0_b1.aoi_r0 A1 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A1 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A1 ) ++ ( read_w0_p1_b1.aoi_r0 A1 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.storage ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A2 ) ( storage_0_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.storage ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( storage_0_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.storage ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( storage_0_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.storage ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( storage_0_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.storage ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A2 ) ( storage_0_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.storage ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( storage_0_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.storage ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( storage_0_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.storage ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A2 ) ( storage_0_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.gclock ( storage_0_0_0.cg GCLK ) ( storage_0_0_0.bit7.bit CLK ) ( storage_0_0_0.bit6.bit CLK ) ( storage_0_0_0.bit5.bit CLK ) ( storage_0_0_0.bit4.bit CLK ) ( storage_0_0_0.bit3.bit CLK ) ( storage_0_0_0.bit2.bit CLK ) ++ ( storage_0_0_0.bit1.bit CLK ) ( storage_0_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_0_0.we ( storage_0_0_0.gcand Y ) ( storage_0_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.gclock ( storage_4_0_0.cg GCLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.gcand Y ) ( storage_4_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.gclock ( storage_5_0_0.cg GCLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.gcand Y ) ( storage_5_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.gclock ( storage_6_0_0.cg GCLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.gcand Y ) ( storage_6_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.gclock ( storage_7_0_0.cg GCLK ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.gcand Y ) ( storage_7_0_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) ( storage_0_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_7_0_0.gcand B ) ( storage_6_0_0.gcand B ) ( storage_5_0_0.gcand B ) ( storage_4_0_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_0_0.gcand B ) ++ ( storage_1_0_0.gcand B ) ( storage_0_0_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_unplaced_asap7.tcl b/src/ram/test/make_8x8_2r1w_unplaced_asap7.tcl +new file mode 100644 +index 0000000000..1f5f9deb61 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_unplaced_asap7.tcl +@@ -0,0 +1,34 @@ ++# generate_ram on asap7, which has no tristate cell: the read ports are ++# AND-OR trees, and the periphery is left for a parent to place: the ++# outline is the placed core, its pins on M4 where their nets land. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_unplaced_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -periphery unplaced \ ++ -pin_layer M4 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_unplaced_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_unplaced_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_unplaced_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_unplaced_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_unplaced_asap7_behavioral.vok +new file mode 100644 +index 0000000000..a5a0666525 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_unplaced_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i]) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index 2876c040c3..20fd131110 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -13,5 +13,6 @@ record_tests { + make_8x8_rb_asap7 + make_8x8_rb_latency_asap7 + make_8x8_2r1w_mux_asap7 ++ make_8x8_2r1w_unplaced_asap7 + make_8x8_latch_sky130 + } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 1da211479..ce7774758 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -179,6 +179,7 @@ test_suite( "@openroad//src/ram/test:make_8x8_2r1w_mux_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_reset_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_unplaced_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_rb_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_rb_latency_asap7-tcl_test", diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index ff3aff04f..8d3c71476 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -162,7 +162,8 @@ ASAP7 = { # stacked, tristate and AND-OR, and 12 words in banks of 3; and with a # banked read port beside a plain one (patch 0016); and with registered # read addresses (patch 0017), on Q and QN flops; and holding words by a -# mux per bit instead of a clock gate (patch 0018). +# mux per bit instead of a clock gate (patch 0018), and with its periphery +# left unplaced (patch 0019). [ [ genrule( @@ -248,5 +249,6 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_mux", NANGATE45, "-storage_cell DFF_X1 -write_style mux", "tb_ram_2w", 8), ("ram_2w_mux_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -read_latency 1", "tb_ram_2w", 8), ("ram_2w_rst_mux_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -write_style mux -reset_value 0xa5", "tb_ram_2w_rst", 8), + ("ram_2w_unplaced_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -periphery unplaced -pin_layer M4", "tb_ram_2w", 8), ] ] From ac4c0f616b90b75a3a4426f58cc7ecee05b563da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 09:31:37 +0200 Subject: [PATCH 19/26] ram: generate_ram -cells and -name (patch 0020) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -cells {role master ...} picks the cell for each role instead of the smallest of its function: on asap7 those are the xp cells ORFS marks dont_use and the hold buffer HB1xp67, which a fixed core cannot resize after; generate_regfile named its cells for that reason. An AOI22 or AO22 given is checked and pinned by its truth table, and findMaster4 reads the pins of the cell it picks rather than the last one matched. -name names the block, so two RAMs of one size can share a design; the ORFS switch onto generate_ram needs both. Tests: the two-write RAM on asap7 with every role given, simulated against its behavioral model; the netlist uses each given cell. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + patches/0020-openroad-ram-cells-name.patch | 377 +++++++++++++++++++++ test/regfile/sim/BUILD.bazel | 3 +- 3 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 patches/0020-openroad-ram-cells-name.patch diff --git a/MODULE.bazel b/MODULE.bazel index 2a3680047..d6cb79d99 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -160,6 +160,9 @@ archive_override( # placed and outlined, for a parent to dissolve. On 0018 (OpenROAD # #11669); not upstreamed. "//patches:0019-openroad-ram-periphery-unplaced.patch", + # 0020: generate_ram -cells {role master ...} and -name. On 0019 + # (OpenROAD #11669); not upstreamed. + "//patches:0020-openroad-ram-cells-name.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0020-openroad-ram-cells-name.patch b/patches/0020-openroad-ram-cells-name.patch new file mode 100644 index 000000000..2ab9767a0 --- /dev/null +++ b/patches/0020-openroad-ram-cells-name.patch @@ -0,0 +1,377 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -cells and -name + +-cells {role master ...} picks the cell for a role (inv, and2, buffer, +clock_gate, aoi22, ao22, or2, nand2, nor2, tie, addr_flop) instead of +the smallest the libraries have of its function. On asap7 the smallest +are the xp cells a flow marks dont_use (INVxp33, AOI22xp33), and the +smallest buffer is the hold buffer HB1xp67; a core the parent keeps +fixed cannot be resized after. An AOI22 or AO22 given is checked by its +truth table, and its pins are read from it; findMaster4 now reads them +from the cell it picks, not from the last that matched in the search. + +-name names the block and the behavioral model, instead of +RAMx, so two RAMs of one size can live in one design. + +The tenth of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 918957177a..fde50b5ba1 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -52,6 +52,8 @@ generate_ram [-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] ++ [-cells {role master ...}] ++ [-name name] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -85,6 +87,8 @@ generate_ram [-mask_size bits] + | `-read_latency` | `1` registers every read port's address, a plain positive-edge flop per address bit, so the data follows a cycle after the address. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. | + | `-write_style` | How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock. Not with `-use_latch`. Default: `clock_gate`. | + | `-periphery`, `-pin_layer` | `generate_ram_netlist` only. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. Default: `placed`. | ++| `-cells` | The cell for a role (`inv`, `and2`, `buffer`, `clock_gate`, `aoi22`, `ao22`, `or2`, `nand2`, `nor2`, `tie`, `addr_flop`), instead of the smallest the libraries have of its function. An AOI22 or AO22 given is checked by its truth table. Default: the smallest of each. | ++| `-name` | The block's and the behavioral model's name. Default: `RAMx`. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index f751f6c63d..eea3100f24 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -120,7 +120,9 @@ class RamGen + int read_latency = 0, + const std::string& write_style = "clock_gate", + const std::string& periphery = "placed", +- const std::string& pin_layer = ""); ++ const std::string& pin_layer = "", ++ const std::string& cells = "", ++ const std::string& name = ""); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -201,7 +203,8 @@ class RamGen + const char* name, + std::array& inputs, + std::string& output, +- bool required = true); ++ bool required = true, ++ odb::dbMaster* given = nullptr); + odb::dbNet* makeNet(const std::string& prefix, const std::string& name); + odb::dbInst* makeInst( + Cell* cell, +@@ -380,6 +383,7 @@ class RamGen + // buffers) left for a parent to place; the outline the placed core and + // a row; each pin where its connections land, on pin_layer_'s tracks + bool periphery_unplaced_{false}; ++ std::string ram_name_; // the block's and the behavioral model's name + std::string pin_layer_; + bool marking_periphery_{false}; + Cell* periphery_cell_{nullptr}; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 4cdfe57e2c..74d6985251 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1310,7 +1311,8 @@ void RamGen::findResetPins() + + // the unused pin of each flop held at its inactive level + const bool off_high = reset_active_low_; +- tie_off_cell_ = findMaster( ++ if (!tie_off_cell_) { ++ tie_off_cell_ = findMaster( + [off_high](sta::LibertyPort* port) { + auto f = port->function(); + return f && port->direction()->isOutput() +@@ -1318,7 +1320,8 @@ void RamGen::findResetPins() + == (off_high ? sta::FuncExpr::Op::one + : sta::FuncExpr::Op::zero); + }, +- off_high ? "tie high" : "tie low"); ++ off_high ? "tie high" : "tie low"); ++ } + tie_off_pin_ = buildPortMap(tie_off_cell_)[{PortRoleType::DataOut, 0}]; + + try { +@@ -1489,10 +1492,12 @@ void RamGen::findMasters() + // aoi cells used for column mux functionality when column_mux_ratio > 1 + // uses truth table simulation to identify AOI22 and discover port names + // to work for all PDKs, avoiding hardcoding PDK-specific expression parsing +- if (!aoi22_cell_) { +- // AOI22 truth table: Y = !(A1&A2 | B1&B2) ++ { ++ // AOI22 truth table: Y = !(A1&A2 | B1&B2); a given cell's pins read ++ // the same way + std::array in; +- aoi22_cell_ = findMaster4(0x0777, "aoi22", in, aoi22_out_); ++ aoi22_cell_ = findMaster4( ++ 0x0777, "aoi22", in, aoi22_out_, /*required=*/true, aoi22_cell_); + aoi22_in_a1_ = in[0]; + aoi22_in_a2_ = in[1]; + aoi22_in_b1_ = in[2]; +@@ -1518,10 +1523,10 @@ void RamGen::findMasters() + + // More than one write port: the write data mux, an AO22 per pair of + // ports, and an OR2 for the write enables and across pairs. +- if ((num_write_ > 1 || write_mux_) && !ao22_cell_) { ++ if (num_write_ > 1 || write_mux_) { + // AO22 truth table: Y = A1&A2 | B1&B2 + ao22_cell_ = findMaster4( +- 0xF888, "ao22", ao22_in_, ao22_out_, /*required=*/false); ++ 0xF888, "ao22", ao22_in_, ao22_out_, /*required=*/false, ao22_cell_); + } + if (num_write_ > 1) { + if (!or2_cell_) { +@@ -1545,7 +1550,8 @@ dbMaster* RamGen::findMaster4(const uint16_t table, + const char* name, + std::array& inputs_out, + std::string& output, +- const bool required) ++ const bool required, ++ dbMaster* given) + { + // for 4 inputs ordered (A1,A2,B1,B2) mapped to bits (0,1,2,3), + // bit k of the table = output when inputs = k in binary. +@@ -1580,8 +1586,7 @@ dbMaster* RamGen::findMaster4(const uint16_t table, + {0, 3, 1, 2}, // group A=(p0,p3), group B=(p1,p2) + }; + +- return findMaster( +- [&](sta::LibertyPort* out_port) -> bool { ++ auto match = [&](sta::LibertyPort* out_port) -> bool { + if (!out_port->direction()->isOutput()) { + return false; + } +@@ -1632,9 +1637,27 @@ dbMaster* RamGen::findMaster4(const uint16_t table, + } + } + return false; +- }, +- name, +- required); ++ }; ++ // the cell given, or the smallest that matches; its pins are read from ++ // it, whichever matched last in the search ++ dbMaster* best = given ? given : findMaster(match, name, required); ++ if (best) { ++ bool matched = false; ++ auto liberty = network_->libertyCell(network_->dbToSta(best)); ++ std::unique_ptr ports( ++ liberty->portIterator()); ++ while (ports->hasNext() && !matched) { ++ auto port = ports->next()->libertyPort(); ++ if (port && port->direction()->isOutput()) { ++ matched = match(port); ++ } ++ } ++ if (!matched) { ++ logger_->error( ++ RAM, 79, "Cell {} is not a {} cell.", best->getName(), name); ++ } ++ } ++ return best; + } + + void RamGen::ramPdngen(const char* power_net_name, +@@ -1890,7 +1913,9 @@ void RamGen::generate(const int mask_size, + const int read_latency, + const std::string& write_style, + const std::string& periphery, +- const std::string& pin_layer) ++ const std::string& pin_layer, ++ const std::string& cells, ++ const std::string& name) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1956,7 +1981,10 @@ void RamGen::generate(const int mask_size, + logger_->error(RAM, 42, "1-row RAMs are not supported."); + } + const int slices_per_word = word_size / mask_size; +- const std::string ram_name = fmt::format("RAM{}x{}", num_words, word_size); ++ // the block's name: -name, or RAMx ++ const std::string ram_name ++ = name.empty() ? fmt::format("RAM{}x{}", num_words, word_size) : name; ++ ram_name_ = ram_name; + + // error checking for column_mux_ratio + if (!banked_ && column_mux_ratio != 1 && column_mux_ratio != 2 +@@ -2021,6 +2049,44 @@ void RamGen::generate(const int mask_size, + nand2_cell_ = nullptr; + nor2_cell_ = nullptr; + latch_cell_ = nullptr; ++ addr_flop_cell_ = nullptr; ++ tie_off_cell_ = nullptr; ++ ++ // -cells {role master ...}: the cell for a role, instead of the ++ // smallest the libraries have of its function ++ { ++ std::istringstream in(cells); ++ std::string role; ++ std::string master_name; ++ const std::map roles ++ = {{"inv", &inv_cell_}, ++ {"and2", &and2_cell_}, ++ {"buffer", &buffer_cell_}, ++ {"clock_gate", &clock_gate_cell_}, ++ {"aoi22", &aoi22_cell_}, ++ {"ao22", &ao22_cell_}, ++ {"or2", &or2_cell_}, ++ {"nand2", &nand2_cell_}, ++ {"nor2", &nor2_cell_}, ++ {"tie", &tie_off_cell_}, ++ {"addr_flop", &addr_flop_cell_}}; ++ while (in >> role >> master_name) { ++ auto slot = roles.find(role); ++ if (slot == roles.end()) { ++ logger_->error(RAM, ++ 80, ++ "-cells: no role {}; the roles are inv, and2, buffer, " ++ "clock_gate, aoi22, ao22, or2, nand2, nor2, tie and " ++ "addr_flop.", ++ role); ++ } ++ dbMaster* master = db_->findMaster(master_name.c_str()); ++ if (master == nullptr) { ++ logger_->error(RAM, 81, "-cells: {} can't be found.", master_name); ++ } ++ *slot->second = master; ++ } ++ } + + if (use_latch_ && storage_cell_) { + auto sta_cell = network_->dbToSta(storage_cell_); +@@ -2062,7 +2128,9 @@ void RamGen::generate(const int mask_size, + }; + // the storage cell where it is one (findMaster passes over cells with + // two outputs, as Nangate45's flops all are), else the smallest +- if (storage_cell_ ++ if (addr_flop_cell_) { ++ // given by -cells ++ } else if (storage_cell_ + && plain(network_->libertyCell(network_->dbToSta(storage_cell_)))) { + addr_flop_cell_ = storage_cell_; + } else { +@@ -3120,7 +3188,7 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + const int address_width + = (num_words <= 1) ? 1 : std::ceil(std::log2(num_words)); + +- std::string module_name = fmt::format("RAM{}x{}", num_words, word_size_bit); ++ std::string module_name = ram_name_; + + int r_total = rw_ports + r_ports; + const int num_write = rw_ports + w_ports; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 1d62729854..b9b51b3a13 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -53,7 +53,9 @@ generate_ram_netlist_cmd(int mask_size, + const int read_latency, + const char* write_style, + const char* periphery, +- const char* pin_layer) ++ const char* pin_layer, ++ const char* cells, ++ const char* name) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -107,7 +109,8 @@ generate_ram_netlist_cmd(int mask_size, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, +- read_latency, write_style, periphery, pin_layer); ++ read_latency, write_style, periphery, pin_layer, cells, ++ name); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 7ae7eb7754..8bafbdd5b6 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -16,6 +16,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] ++ [-cells {role master ...}] ++ [-name name] + [-zero_word word] + [-reset_value value] + [-banks count] +@@ -26,6 +28,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-write_style clock_gate|mux] + [-periphery placed|unplaced] + [-pin_layer layer] ++ [-cells {role master ...}] ++ [-name name] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -40,7 +44,7 @@ proc generate_ram_netlist { args } { + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -periphery -pin_layer } flags {} ++ -periphery -pin_layer -cells -name } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -201,6 +205,17 @@ proc generate_ram_netlist { args } { + set pin_layer $keys(-pin_layer) + } + ++ # {role master ...}: the cell for a role, instead of the smallest of its ++ # function; and the block's name, instead of RAMx ++ set cells "" ++ if { [info exists keys(-cells)] } { ++ set cells [join $keys(-cells) " "] ++ } ++ set name "" ++ if { [info exists keys(-name)] } { ++ set name $keys(-name) ++ } ++ + # How a word holds its value between writes: a clock gate per word + # (clock_gate), or a mux per bit (mux). + set write_style clock_gate +@@ -233,7 +248,7 @@ proc generate_ram_netlist { args } { + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ +- $rb_ports $read_latency $write_style $periphery $pin_layer ++ $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -268,7 +283,8 @@ proc generate_ram { args } { + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports -read_latency -write_style } flags {} ++ -banks -bank_columns -bank_order -rb_ports -read_latency -write_style ++ -cells -name } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -317,7 +333,8 @@ proc generate_ram { args } { + lappend ram_netlist_args -reset_value $keys(-reset_value) + } + +- foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style} { ++ foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style ++ -cells -name} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 8d3c71476..92c3b211f 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -163,7 +163,7 @@ ASAP7 = { # banked read port beside a plain one (patch 0016); and with registered # read addresses (patch 0017), on Q and QN flops; and holding words by a # mux per bit instead of a clock gate (patch 0018), and with its periphery -# left unplaced (patch 0019). +# left unplaced (patch 0019); and with cells given by role (patch 0020). [ [ genrule( @@ -250,5 +250,6 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_mux_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -read_latency 1", "tb_ram_2w", 8), ("ram_2w_rst_mux_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -write_style mux -reset_value 0xa5", "tb_ram_2w_rst", 8), ("ram_2w_unplaced_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -periphery unplaced -pin_layer M4", "tb_ram_2w", 8), + ("ram_2w_cells_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -cells {inv INVx1_ASAP7_75t_R and2 AND2x2_ASAP7_75t_R buffer BUFx2_ASAP7_75t_R aoi22 AOI22x1_ASAP7_75t_R ao22 AO22x2_ASAP7_75t_R or2 OR2x2_ASAP7_75t_R nand2 NAND2x1_ASAP7_75t_R nor2 NOR2x1_ASAP7_75t_R} -name RAM8x8", "tb_ram_2w", 8), ] ] From 5b4c0ff7710842b8d0ffc8c7e7ddae0fb5af60fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 10:08:42 +0200 Subject: [PATCH 20/26] regfile: AUTO_MEMORIES_REGFILES through generate_ram (ORFS 0109, OpenROAD 0021) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ORFS patch 0109: a register-file spec generate_ram can build is built by it. memories/regfile_ram.py translates the spec to generate_ram_netlist's options and writes a wrapper in the RTL module's place connecting its ports (widths from the yosys JSON) to generate_ram's, a reset's polarity adapted there; the RAM, _ram, is inlined, or in mode netlist a macro with its periphery unplaced that regfile_dissolve.tcl dissolves as before. Specs with flop names for equivalence checking, folded bits or a Verilog periphery, and macros kept to the end, stay with generate_regfile for now. The translation names generate_regfile's asap7 cells where a spec names none, and NOR2x1, measured: NOR2xp33 at the read tree's root cost 23 ps. OpenROAD patch 0021: -decoder word, a balanced AND2 tree per word, as the banks decode; generate_ram's row decoder is an AND2 chain, about 60 ps of riscv32i's 220 ps read path. riscv32i, global route, placement parasitics, 950 ps clock: shape generator core period inlined, 62 % generate_regfile 3544 um2 944 ps inlined, 62 % generate_ram 3503 um2 943 ps netlist, 55 %, 2 um ch. generate_regfile 4283 um2 938 ps netlist, 55 %, 2 um ch. generate_ram 3968 um2 945 ps netlist, 62 %, 2 um ch. generate_ram 3512 um2 939 ps The macro-placed shape now fits riscv32i's own 62 % and matches the inlined one: the dissolved core is 55.3 x 8.6 um, 93 % cells, where generate_regfile's padded abstract was 48 %. At riscv32i's 8 um channels it does not fit (MPL-0006). test/regfile: the macro is RegFile_ram behind the wrapper; the blackbox, keep-synth and dissolve-probe expectations say so, and the probe finds the dissolved cells under the wrapper's instance. The ledger matches riscv.dp/rf.ram. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + orfs_source.bzl | 5 + patches/0021-openroad-ram-word-decoder.patch | 167 +++++++ patches/0109-orfs-regfiles-generate-ram.patch | 452 ++++++++++++++++++ test/regfile/BUILD.bazel | 14 +- test/regfile/dissolve_probe.tcl | 43 +- test/regfile/riscv32i/ledger.tcl | 2 +- 7 files changed, 671 insertions(+), 15 deletions(-) create mode 100644 patches/0021-openroad-ram-word-decoder.patch create mode 100644 patches/0109-orfs-regfiles-generate-ram.patch diff --git a/MODULE.bazel b/MODULE.bazel index d6cb79d99..b2b7cfd4f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -163,6 +163,9 @@ archive_override( # 0020: generate_ram -cells {role master ...} and -name. On 0019 # (OpenROAD #11669); not upstreamed. "//patches:0020-openroad-ram-cells-name.patch", + # 0021: generate_ram -decoder word, a balanced AND2 tree per word. + # On 0020 (OpenROAD #11669); not upstreamed. + "//patches:0021-openroad-ram-word-decoder.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/orfs_source.bzl b/orfs_source.bzl index e4561d968..0f1585f91 100644 --- a/orfs_source.bzl +++ b/orfs_source.bzl @@ -164,6 +164,11 @@ ORFS_PATCHES = [ # in the module's place. On 0089 and 0091; retires with 0089. Not # upstreamed. Label("//patches:0108-orfs-regfile-periphery-verilog.patch"), + # 0109: register files through generate_ram (OpenROAD patches 0011 to + # 0020) where it builds the spec, a wrapper in the RTL module's place; + # the rest stay with generate_regfile. On 0089, 0091 and 0108; retires + # with 0089. Not upstreamed. + Label("//patches:0109-orfs-regfiles-generate-ram.patch"), ] # Generate the BUILD file for any design directory that has a config.mk diff --git a/patches/0021-openroad-ram-word-decoder.patch b/patches/0021-openroad-ram-word-decoder.patch new file mode 100644 index 000000000..26f2b3912 --- /dev/null +++ b/patches/0021-openroad-ram-word-decoder.patch @@ -0,0 +1,167 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -decoder word, a balanced tree per word + +-decoder word decodes each word's whole address through a balanced +AND2 tree, the banks' decoders (patch 0015) without banks. The default, +row, is generate_ram's decoder per row, an AND2 chain over the row +address: four AND2 deep for 32 rows where a tree is three. On riscv32i's +register file the chain is about 60 ps of the read path's 220. + +The eleventh of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index fde50b5ba1..abbbca09f7 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -54,6 +54,7 @@ generate_ram [-mask_size bits] + [-write_style clock_gate|mux] + [-cells {role master ...}] + [-name name] ++ [-decoder row|word] + [-inv_cell name] + [-power_net_name name] + [-ground_net_name name] +@@ -89,6 +90,7 @@ generate_ram [-mask_size bits] + | `-periphery`, `-pin_layer` | `generate_ram_netlist` only. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. Default: `placed`. | + | `-cells` | The cell for a role (`inv`, `and2`, `buffer`, `clock_gate`, `aoi22`, `ao22`, `or2`, `nand2`, `nor2`, `tie`, `addr_flop`), instead of the smallest the libraries have of its function. An AOI22 or AO22 given is checked by its truth table. Default: the smallest of each. | + | `-name` | The block's and the behavioral model's name. Default: `RAMx`. | ++| `-decoder` | `row`: a decoder per row, an AND2 chain over the row address, the column mux selecting within the row. `word`: a balanced AND2 tree over each word's whole address, as with banks; shallower for the read path. Default: `row`. | + | `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. | + | `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. | + | `-power_net_name` | Name of the power net to create. Default: `VDD`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index eea3100f24..d253b23818 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -122,7 +122,8 @@ class RamGen + const std::string& periphery = "placed", + const std::string& pin_layer = "", + const std::string& cells = "", +- const std::string& name = ""); ++ const std::string& name = "", ++ const std::string& decoder = "row"); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 74d6985251..b5a03e9315 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -1915,12 +1915,15 @@ void RamGen::generate(const int mask_size, + const std::string& periphery, + const std::string& pin_layer, + const std::string& cells, +- const std::string& name) ++ const std::string& name, ++ const std::string& decoder) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; + // without banks, the column mux as it was. +- banked_ = banks > 1 || bank_columns > 1; ++ // -decoder word: each port decodes every word's whole address through ++ // a balanced AND2 tree per word, the banks' decoders, banks or none ++ banked_ = banks > 1 || bank_columns > 1 || decoder == "word"; + banks_ = std::max(banks, 1); + bank_columns_ = std::max(bank_columns, 1); + bank_interleaved_ = bank_order == "interleaved"; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index b9b51b3a13..6fdfcf5eda 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -55,7 +55,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* periphery, + const char* pin_layer, + const char* cells, +- const char* name) ++ const char* name, ++ const char* decoder) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -110,7 +111,7 @@ generate_ram_netlist_cmd(int mask_size, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, + read_latency, write_style, periphery, pin_layer, cells, +- name); ++ name, decoder); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 8bafbdd5b6..1b056eaabf 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -18,6 +18,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-write_style clock_gate|mux] + [-cells {role master ...}] + [-name name] ++ [-decoder row|word] + [-zero_word word] + [-reset_value value] + [-banks count] +@@ -30,6 +31,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-pin_layer layer] + [-cells {role master ...}] + [-name name] ++ [-decoder row|word] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -44,7 +46,7 @@ proc generate_ram_netlist { args } { + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -periphery -pin_layer -cells -name } flags {} ++ -periphery -pin_layer -cells -name -decoder } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -216,6 +218,17 @@ proc generate_ram_netlist { args } { + set name $keys(-name) + } + ++ # The address decoders: row, a decoder per row (an AND2 chain), the ++ # column mux selecting within it; or word, a balanced AND2 tree over ++ # each word's whole address. ++ set decoder row ++ if { [info exists keys(-decoder)] } { ++ set decoder $keys(-decoder) ++ if { $decoder ni {row word} } { ++ utl::error RAM 82 "-decoder is row or word, not $decoder." ++ } ++ } ++ + # How a word holds its value between writes: a clock gate per word + # (clock_gate), or a mux per bit (mux). + set write_style clock_gate +@@ -248,7 +261,8 @@ proc generate_ram_netlist { args } { + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ +- $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name ++ $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name \ ++ $decoder + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -284,7 +298,7 @@ proc generate_ram { args } { + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -cells -name } flags {} ++ -cells -name -decoder } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -334,7 +348,7 @@ proc generate_ram { args } { + } + + foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -cells -name} { ++ -cells -name -decoder} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } diff --git a/patches/0109-orfs-regfiles-generate-ram.patch b/patches/0109-orfs-regfiles-generate-ram.patch new file mode 100644 index 000000000..2cad1b106 --- /dev/null +++ b/patches/0109-orfs-regfiles-generate-ram.patch @@ -0,0 +1,452 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] AUTO_MEMORIES_REGFILES: register files through generate_ram + +A register-file spec that generate_ram can build is built by it, not by +generate_regfile: memories/regfile_ram.py translates the spec to +generate_ram_netlist's options (OpenROAD patches 0011 to 0020) and +writes a wrapper in the RTL module's place connecting its ports, from +the design's yosys JSON, to generate_ram's, a reset's polarity adapted +there. The wrapper is always inlined; the RAM, _ram, is inlined +too, or in mode netlist a macro with its periphery unplaced that +regfile_dissolve.tcl dissolves as before (a netlist of one instance a +line, a .place file, write_abstract_lef's LEF, a liberty of area and +pins). A spec using a key generate_ram lacks yet (flop names for +equivalence checking, folded bits, the periphery as Verilog), or kept +as a macro to the end, stays with generate_regfile. + +On 0089, 0091 and 0108. Not upstreamed: AUTO_MEMORIES_REGFILES is +carried here only. Retires with 0089. + +--- +diff --git a/flow/scripts/memories/gen_memories.py b/flow/scripts/memories/gen_memories.py +--- a/flow/scripts/memories/gen_memories.py ++++ b/flow/scripts/memories/gen_memories.py +@@ -37,6 +37,7 @@ + + import detect # noqa: E402 + import idiomatic # noqa: E402 ++import regfile_ram # noqa: E402 + import schema # noqa: E402 + + FAKERAM_RUN_PY = Path(__file__).resolve().parents[3] / "tools/FakeRAM2.0/run.py" +@@ -232,6 +233,24 @@ + inline = [] + for spec, module in zip(specs, modules): + mode = _spec_mode(spec) ++ # generate_ram, Austin Rovinski's generator, where it builds the ++ # spec: the RTL module's place taken by a wrapper around the RAM ++ shape = mode if module in macro_place else "inline" ++ if regfile_ram.supported(spec, shape): ++ ram = regfile_ram.generate(spec, module, shape, openroad, lefs, out_dir) ++ memories.append( ++ _regfile_memory(spec, module, f"register file, generate_ram, {shape}") ++ ) ++ inline.append(module) ++ if ram["macro"]: ++ cores.append(ram["block"]) ++ if ram["dissolve"]: ++ dissolve.append(ram["block"]) ++ sys.stderr.write( ++ f"gen_memories: {module} -> register file, generate_ram, " ++ f"{shape} ({spec.name})\n" ++ ) ++ continue + rtl = _file_defining(module, verilog) + tcl = out_dir / f"{module}.generate.tcl" + if module not in macro_place: +diff --git a/flow/scripts/memories/regfile_ram.py b/flow/scripts/memories/regfile_ram.py +new file mode 100644 +--- /dev/null ++++ b/flow/scripts/memories/regfile_ram.py +@@ -0,0 +1,391 @@ ++"""AUTO_MEMORIES_REGFILES through OpenROAD's generate_ram. ++ ++A register-file spec (the keys generate_regfile reads) is translated to ++generate_ram_netlist's options, and the generated RAM, a block named ++_ram, stands in for the RTL module through a wrapper written in ++the module's place: its ports, from the design's yosys JSON, connected ++to generate_ram's (clk, rst_n, D0, we0, addr_w0, addr_r0, Q0, ...), an ++active-high reset inverted for an active-low flop. The wrapper is ++always inlined; the RAM is ++ ++- inlined: its netlist follows the wrapper in .v; ++- mode netlist: a macro with its periphery unplaced, which ++ regfile_dissolve.tcl dissolves after macro placement from ++ _ram.v (one instance a line) and _ram.place; ++A spec using a key generate_ram does not have yet (flop names for ++equivalence checking, folded bits, the periphery as Verilog), or kept ++as a macro to the end, is left to generate_regfile; supported() says ++which. ++""" ++ ++from __future__ import annotations ++ ++import json ++import math ++import os ++import subprocess ++from pathlib import Path ++ ++# keys generate_ram has no counterpart for yet ++UNSUPPORTED = {"store_name", "read_reg_name", "bit_folds", "pin_track", "lib"} ++ ++# a spec's `cell ` roles, as generate_ram's -cells names them ++CELL_ROLES = { ++ "inv": "inv", ++ "and2": "and2", ++ "or2": "or2", ++ "ao22": "ao22", ++ "aoi22": "aoi22", ++ "nand2": "nand2", ++ "nor2": "nor2", ++ "icg": "clock_gate", ++ "tie_hi": "tie", ++ "buffer": "buffer", ++} ++ ++ ++# AUTO_MEMORIES is asap7's ++DEFAULT_CELLS = { ++ "aoi22": "AOI22xp5_ASAP7_75t_R", ++ "nand2": "NAND2xp5_ASAP7_75t_R", ++ "nor2": "NOR2x1_ASAP7_75t_R", ++ "buffer": "BUFx2_ASAP7_75t_R", ++} ++ ++ ++def parse(spec: Path) -> list[list[str]]: ++ """The spec's lines as [key, value, ...], comments and blanks out.""" ++ lines = [] ++ for line in spec.read_text().splitlines(): ++ words = line.split("#", 1)[0].split() ++ if words: ++ lines.append(words) ++ return lines ++ ++ ++def _values(lines: list[list[str]], key: str) -> list[list[str]]: ++ return [line[1:] for line in lines if line[0] == key] ++ ++ ++def _one(lines: list[list[str]], key: str, default: str = "") -> str: ++ values = _values(lines, key) ++ return values[-1][0] if values and values[-1] else default ++ ++ ++def supported(spec: Path, shape: str) -> bool: ++ """Whether generate_ram builds this spec in this shape (inline, ++ netlist or macro). A macro kept to the end needs its pins placed, ++ which generate_ram_netlist does only with its periphery unplaced.""" ++ lines = parse(spec) ++ keys = {line[0] for line in lines} ++ return ( ++ not (keys & UNSUPPORTED) ++ and _one(lines, "periphery") != "verilog" ++ and shape != "macro" ++ ) ++ ++ ++def _address_bits(words: int) -> int: ++ return max(1, math.ceil(math.log2(words))) ++ ++ ++def _args(lines: list[list[str]], block: str, shape: str) -> list[str]: ++ """generate_ram_netlist's options for the spec.""" ++ words = int(_one(lines, "words")) ++ bits = int(_one(lines, "bits")) ++ cells = {line[1]: line[2] for line in lines if line[0] == "cell"} ++ async_reset = _values(lines, "async_reset") ++ storage = cells.get("flop_r" if async_reset else "flop") ++ args = [ ++ "-name", ++ block, ++ "-mask_size", ++ str(bits), ++ "-word_size", ++ str(bits), ++ "-num_words", ++ str(words), ++ "-r_ports", ++ str(len(_values(lines, "read"))), ++ "-w_ports", ++ str(len(_values(lines, "write"))), ++ "-write_style", ++ _one(lines, "write_style", "mux"), ++ # a balanced tree per word, as generate_regfile decodes ++ "-decoder", ++ "word", ++ ] ++ if storage: ++ args += ["-storage_cell", storage] ++ if _values(lines, "read_banked"): ++ args += ["-rb_ports", str(len(_values(lines, "read_banked")))] ++ for key in ("zero_word", "banks", "bank_columns", "bank_order", "read_latency"): ++ if _values(lines, key): ++ args += [f"-{key}", _one(lines, key)] ++ if async_reset: ++ args += ["-reset_value", "0"] ++ # generate_regfile's asap7 defaults where the spec names no cell, and ++ # a buffer for the select buffers (the smallest asap7 buffer is the ++ # hold buffer HB1xp67) ++ cells = DEFAULT_CELLS | cells ++ roles = [ ++ f"{CELL_ROLES[role]} {master}" ++ for role, master in cells.items() ++ if role in CELL_ROLES ++ ] ++ if roles: ++ args += ["-cells", "{" + " ".join(roles) + "}"] ++ if shape == "netlist": ++ args += ["-periphery", "unplaced", "-pin_layer", _one(lines, "pin_layer", "M4")] ++ return args ++ ++ ++# The second session's Tcl: the generated block's ports, and for a macro ++# its views, from its database. ++_VIEWS_TCL = r""" ++set block [ord::get_db_block] ++set f [open {out}/{block}.ports w] ++foreach term [$block getBTerms] {{ ++ if {{[$term getSigType] in {{POWER GROUND}}}} {{ continue }} ++ puts $f "[$term getName] [$term getIoType]" ++}} ++close $f ++""" ++ ++_MACRO_TCL = r""" ++# the netlist, one instance a line, as regfile_dissolve.tcl reads it ++set f [open {out}/{block}.v w] ++foreach inst [$block getInsts] {{ ++ set conns {{}} ++ foreach it [$inst getITerms] {{ ++ set net [$it getNet] ++ if {{$net eq "NULL" || [$net getSigType] in {{POWER GROUND}}}} {{ continue }} ++ lappend conns ".[[$it getMTerm] getName](\\[$net getName] )" ++ }} ++ puts $f "[[$inst getMaster] getName] \\[$inst getName] ([join $conns {{, }}]);" ++}} ++close $f ++# where each placed cell is, as the generator laid it out ++set f [open {out}/{block}.place w] ++foreach inst [$block getInsts] {{ ++ if {{![$inst isPlaced]}} {{ continue }} ++ lassign [$inst getLocation] x y ++ puts $f "[$inst getName] $x $y [$inst getOrient]" ++}} ++close $f ++write_abstract_lef {out}/{block}.lef ++# a liberty of its area and pins: a blackbox to synthesis ++set dbu [[ord::get_db_tech] getDbUnitsPerMicron] ++set die [$block getDieArea] ++set area [expr {{double([$die dx]) / $dbu * [$die dy] / $dbu}}] ++set f [open {out}/{block}.lib w] ++puts $f "library({block}) {{" ++puts $f " delay_model : table_lookup;" ++puts $f " time_unit : \"1ns\";" ++puts $f " voltage_unit : \"1V\";" ++puts $f " current_unit : \"1uA\";" ++puts $f " leakage_power_unit : \"1uW\";" ++puts $f " capacitive_load_unit (1,pf);" ++puts $f " pulling_resistance_unit : \"1kohm\";" ++set buses [dict create] ++foreach term [$block getBTerms] {{ ++ if {{[$term getSigType] in {{POWER GROUND}}}} {{ continue }} ++ set name [$term getName] ++ set dir [expr {{[$term getIoType] eq "INPUT" ? "input" : "output"}}] ++ if {{[regexp {{^(.*)\[(\d+)\]$}} $name -> base index]}} {{ ++ set hi [expr {{[dict exists $buses $base] ? max([lindex [dict get $buses $base] 1], $index) : $index}}] ++ dict set buses $base [list $dir $hi] ++ }} else {{ ++ dict set buses $name [list $dir -1] ++ }} ++}} ++set widths {{}} ++dict for {{name info}} $buses {{ ++ set hi [lindex $info 1] ++ if {{$hi >= 0 && [lsearch $widths [expr {{$hi + 1}}]] < 0}} {{ lappend widths [expr {{$hi + 1}}] }} ++}} ++foreach w $widths {{ ++ puts $f " type ({block}_bus_$w) {{ base_type : array; data_type : bit; bit_width : $w; bit_from : [expr {{$w - 1}}]; bit_to : 0; downto : true; }}" ++}} ++puts $f " cell({block}) {{" ++puts $f " area : $area;" ++puts $f " is_macro_cell : true;" ++puts $f " dont_touch : true;" ++dict for {{name info}} $buses {{ ++ lassign $info dir hi ++ if {{$hi < 0}} {{ ++ puts $f " pin($name) {{ direction : $dir; capacitance : 0.001; }}" ++ }} else {{ ++ puts $f " bus($name) {{ bus_type : {block}_bus_[expr {{$hi + 1}}]; direction : $dir; capacitance : 0.001; }}" ++ }} ++}} ++puts $f " }}" ++puts $f "}}" ++close $f ++""" ++ ++ ++def _module_ports(yosys_json: Path, module: str) -> dict[str, tuple[str, int]]: ++ """The RTL module's ports, name -> (direction, width), from the ++ design's yosys JSON; empty where it does not have the module.""" ++ if not yosys_json.exists(): ++ return {} ++ modules = json.loads(yosys_json.read_text()).get("modules", {}) ++ for name, body in modules.items(): ++ if name.lstrip("\\") == module: ++ return { ++ port: (info["direction"], len(info["bits"])) ++ for port, info in body.get("ports", {}).items() ++ } ++ return {} ++ ++ ++def _buses(port_lines: list[str]) -> dict[str, tuple[str, int]]: ++ """generate_ram's ports, base name -> (direction, width).""" ++ buses: dict[str, tuple[str, int]] = {} ++ for line in port_lines: ++ name, io = line.split() ++ base, width = name, 1 ++ if name.endswith("]") and "[" in name: ++ base = name[: name.rindex("[")] ++ width = int(name[name.rindex("[") + 1 : -1]) + 1 ++ direction = "input" if io == "INPUT" else "output" ++ old = buses.get(base, (direction, 0))[1] ++ buses[base] = (direction, max(old, width)) ++ return buses ++ ++ ++def _wrapper( ++ lines: list[list[str]], ++ module: str, ++ block: str, ++ ram_ports: dict[str, tuple[str, int]], ++ rtl_ports: dict[str, tuple[str, int]], ++) -> str: ++ """The module the RTL's stands in for: its ports to generate_ram's.""" ++ words = int(_one(lines, "words")) ++ bits = int(_one(lines, "bits")) ++ banks = int(_one(lines, "banks", "1")) ++ conns: dict[str, str] = {} ++ widths: dict[str, tuple[str, int]] = {} ++ ++ def port(name: str, direction: str, width: int) -> str: ++ widths.setdefault(name, rtl_ports.get(name, (direction, width))) ++ return name ++ ++ def fit(name: str, width: int) -> str: ++ """An RTL address as wide as generate_ram's.""" ++ have = widths[name][1] ++ if have == width: ++ return name ++ if have > width: ++ return f"{name}[{width - 1}:0]" ++ return f"{{{width - have}'b0, {name}}}" ++ ++ conns["clk"] = port(_one(lines, "clock", "clock"), "input", 1) ++ for values in _values(lines, "reset"): ++ port(values[0], "input", 1) ++ for values in _values(lines, "unused"): ++ port(values[0], "input", 1) ++ for values in _values(lines, "async_reset"): ++ name = port(values[0], "input", 1) ++ low = values[1] == "low" if len(values) > 1 else True ++ if "rst_n" in ram_ports: ++ conns["rst_n"] = name if low else f"~{name}" ++ else: ++ conns["rst"] = f"~{name}" if low else name ++ reads = _values(lines, "read") ++ a = _address_bits(words) ++ for i, (addr, data) in enumerate(reads): ++ conns[f"addr_r{i}"] = fit(port(addr, "input", a), a) ++ conns["Q" if len(reads) == 1 else f"Q{i}"] = port(data, "output", bits) ++ writes = _values(lines, "write") ++ for w, values in enumerate(writes): ++ suffix = "" if len(writes) == 1 else str(w) ++ conns[f"addr_w{suffix}"] = fit(port(values[0], "input", a), a) ++ conns[f"D{suffix}"] = port(values[1], "input", bits) ++ conns[f"we{suffix}"] = ( ++ port(values[2], "input", 1) if len(values) > 2 else "1'b1" ++ ) ++ ab = _address_bits(words // banks) ++ for k, values in enumerate(_values(lines, "read_banked")): ++ for b in range(len(values) // 2): ++ conns[f"addr_rb{k}_b{b}"] = fit(port(values[2 * b], "input", ab), ab) ++ conns[f"Qrb{k}_b{b}"] = port(values[2 * b + 1], "output", bits) ++ for name in ram_ports: ++ if name not in conns: ++ raise SystemExit( ++ f"regfile_ram: {module}: generate_ram's port {name} has no " ++ "counterpart in the spec" ++ ) ++ # the RTL's ports in its own order where the JSON has them ++ order = list(rtl_ports) or list(widths) ++ for name in widths: ++ if name not in order: ++ order.append(name) ++ decl = [] ++ for name in order: ++ direction, width = widths[name] if name in widths else rtl_ports[name] ++ decl.append( ++ f" {direction} {'' if width == 1 else f'[{width - 1}:0] '}{name}" ++ ) ++ body = ",\n".join(decl) ++ inst = ",\n".join(f" .{p}({c})" for p, c in conns.items()) ++ return ( ++ f"// generated by regfile_ram.py: {module} as generate_ram's {block}\n" ++ f"module {module} (\n{body}\n);\n {block} ram (\n{inst}\n );\nendmodule\n" ++ ) ++ ++ ++def generate( ++ spec: Path, ++ module: str, ++ shape: str, ++ openroad: str, ++ lefs: list[Path], ++ out_dir: Path, ++) -> dict: ++ """Build the spec's RAM, shape inline, netlist or macro; return what ++ the flow lists: the block, and whether it is a macro and dissolves.""" ++ lines = parse(spec) ++ block = f"{module}_ram" ++ libs = os.environ.get("LIB_FILES", "").split() ++ if not libs: ++ raise SystemExit("regfile_ram: generate_ram needs LIB_FILES") ++ reads = "".join(f"read_liberty {lib}\n" for lib in libs) ++ gen = out_dir / f"{module}.generate.tcl" ++ gen.write_text( ++ reads ++ + "".join(f"read_lef {lef}\n" for lef in lefs) ++ + "generate_ram_netlist " ++ + " ".join(_args(lines, block, shape)) ++ + f"\nwrite_db {out_dir / f'{block}.odb'}\n" ++ ) ++ subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(gen)]) ++ views = out_dir / f"{module}.views.tcl" ++ tcl = reads + f"read_db {out_dir / f'{block}.odb'}\n" ++ tcl += _VIEWS_TCL.format(out=out_dir, block=block) ++ if shape == "inline": ++ tcl += f"write_verilog {out_dir / f'{block}.netlist.v'}\n" ++ else: ++ tcl += _MACRO_TCL.format(out=out_dir, block=block) ++ views.write_text(tcl) ++ subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(views)]) ++ ram_ports = _buses((out_dir / f"{block}.ports").read_text().splitlines()) ++ rtl_ports = _module_ports(out_dir.parent / "memories_inferred.json", module) ++ wrapper = _wrapper(lines, module, block, ram_ports, rtl_ports) ++ if shape == "inline": ++ wrapper += "\n" + (out_dir / f"{block}.netlist.v").read_text() ++ else: ++ # the macro, a blackbox to synthesis ++ decl = ",\n".join( ++ f" {d} {'' if w == 1 else f'[{w - 1}:0] '}{n}" ++ for n, (d, w) in ram_ports.items() ++ ) ++ wrapper += f"\n(* blackbox *)\nmodule {block} (\n{decl}\n);\nendmodule\n" ++ (out_dir / f"{module}.v").write_text(wrapper) ++ return { ++ "block": block, ++ "macro": shape != "inline", ++ "dissolve": shape == "netlist", ++ } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index ce7774758..10eeffda0 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -128,7 +128,9 @@ filegroup( ) # Synthesis reached its netlist, and the register file is a macro -# instance, not a module of its own. +# instance, not a module of its own: generate_ram's RegFile_ram, behind +# the wrapper in RegFile's place (ORFS patch 0109), which hierarchical +# synthesis may keep. sh_test( name = "regfile_top_keep_synth_test", size = "small", @@ -136,20 +138,22 @@ sh_test( args = [ "$(location :regfile_top_keep_synth_netlist)", "regfile_top", - "!RegFile", + "!RegFile_ram", ], data = [":regfile_top_keep_synth_netlist"], ) -# The register file's line in blackboxes.txt is `RegFile `. +# The register file's line in blackboxes.txt is `RegFile_ram `: +# generate_ram's RAM is the macro, a wrapper in RegFile's place (ORFS +# patch 0109). genrule( name = "regfile_top_keep_blackboxes", srcs = [":regfile_top_keep_synth"], outs = ["regfile_top_keep_blackboxes.txt"], cmd = "files=$$(echo $(locations :regfile_top_keep_synth) | tr ' ' '\\n'); " + "bb=$$(echo \"$$files\" | grep '/memories$$')/blackboxes.txt; " + - "grep -Eq '^RegFile [0-9]+[.][0-9]+$$' $$bb || " + - "{ echo 'no `RegFile ` line in blackboxes.txt'; cat $$bb; exit 1; }; " + + "grep -Eq '^RegFile_ram [0-9]+[.][0-9]+$$' $$bb || " + + "{ echo 'no `RegFile_ram ` line in blackboxes.txt'; cat $$bb; exit 1; }; " + "cp $$bb $@", ) diff --git a/test/regfile/dissolve_probe.tcl b/test/regfile/dissolve_probe.tcl index e931c6809..76c468e84 100644 --- a/test/regfile/dissolve_probe.tcl +++ b/test/regfile/dissolve_probe.tcl @@ -1,17 +1,42 @@ # What the macro step left of test/regfile's regfile_top register file, as JSON: -# whether the RegFile macro is gone, its cells by kind, and the facts -# check_dissolve.py asserts. The core is the cells memories/RegFile.place -# names; the rest under u_rf/ is the periphery. +# whether the macro is gone, its cells by kind, and the facts +# check_dissolve.py asserts. The macro is generate_ram's RegFile_ram behind +# a wrapper in RegFile's place (ORFS patch 0109), or generate_regfile's +# RegFile; the core is the cells its .place file names, the rest under its +# instance the periphery. # The stage's ODB is ODB_FILE, in another repository's results directory: # read it directly, and the generator's files from beside it. read_db $::env(ODB_FILE) set block [ord::get_db_block] -set place [dict create] -set f [open [file dirname $::env(ODB_FILE)]/memories/RegFile.place r] +set memories [file dirname $::env(ODB_FILE)]/memories +set macro_master RegFile_ram +if { ![file exists $memories/$macro_master.place] } { set macro_master RegFile } +set names {} +set f [open $memories/$macro_master.place r] while { [gets $f line] >= 0 } { - if { [lindex $line 0] ne "" } { dict set place "u_rf/[lindex $line 0]" 1 } + if { [lindex $line 0] ne "" } { lappend names [lindex $line 0] } } close $f +# the dissolved cells' prefix: the macro's instance, u_rf/ or, inside the +# flattened wrapper, u_rf.ram/ +# (a cell the parent never reads is gone as dead logic: try names until +# one is there) +set prefix u_rf/ +foreach name $names { + set found "" + foreach candidate {u_rf/ u_rf.ram/ u_rf/ram/} { + if { [$block findInst "$candidate$name"] ne "NULL" } { + set found $candidate + break + } + } + if { $found ne "" } { + set prefix $found + break + } +} +set place [dict create] +foreach name $names { dict set place "$prefix$name" 1 } set row_orient [dict create] foreach row [$block getRows] { dict set row_orient [[$row getBBox] yMin] [$row getOrient] @@ -27,9 +52,9 @@ set periphery_placed 0 set stray_firm 0 foreach inst [$block getInsts] { set master [$inst getMaster] - if { [$master getName] eq "RegFile" } { incr macros } + if { [$master getName] eq $macro_master } { incr macros } set name [$inst getName] - if { ![string match u_rf/* $name] } { continue } + if { ![string match "$prefix*" $name] } { continue } if { [dict exists $place $name] } { incr core if { [$inst getPlacementStatus] eq "FIRM" } { incr core_firm } @@ -52,7 +77,7 @@ foreach inst [$block getInsts] { } set internal_nets 0 foreach net [$block getNets] { - if { [string match u_rf/* [$net getName]] && [$net isDoNotTouch] } { incr internal_nets } + if { [string match "$prefix*" [$net getName]] && [$net isDoNotTouch] } { incr internal_nets } } set out [open $::env(OUTPUT_JSON) w] puts $out "{" diff --git a/test/regfile/riscv32i/ledger.tcl b/test/regfile/riscv32i/ledger.tcl index 1f880a914..63ed33b2e 100644 --- a/test/regfile/riscv32i/ledger.tcl +++ b/test/regfile/riscv32i/ledger.tcl @@ -29,7 +29,7 @@ foreach i [$b getInsts] { if {[string match *WELLTAP $t] || [string match ENDCAP* $t] || [string match TAP* [$i getName]] || [string match PHY_* [$i getName]]} { set tap [expr {$tap+$a}]; continue } if {[string match *FILL* [$m getName]] || [string match *DECAP* [$m getName]]} { set fill [expr {$fill+$a}]; continue } if {![$i isPlaced]} { set unplaced [expr {$unplaced+$a}] } - if {[string match {riscv.dp[./]rf/*} [$i getName]]} { + if {[string match {riscv.dp[./]rf[./]*} [$i getName]]} { set rf [expr {$rf+$a}]; incr nrf if {[$i getPlacementStatus] eq "FIRM"} { set bb [$i getBBox]; set rfbox [expr {$rfbox+$a}] From e6902658716a7fefaa8bd415d1b69e1f74e1b206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 10:36:03 +0200 Subject: [PATCH 21/26] ram: generate_ram -bit_folds, a word in rows (patch 0022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_ram puts a word in one row, a bit's cells side by side, so a wide word with many ports is a long thin array: XiangShan's integer register file (64 bits, 12 read and 9 write ports) came out 1458 x 31 um. -bit_folds k lays the word's slices in k rows; the decoder, select-buffer and address-inverter columns take k rows a word. A folded word is written whole, one write enable a port, and its write logic is built in its first fold and shared by the others: as mask slices, the folds had each repeated it. ORFS 0109 translates a spec's bit_folds, and with store_name and read_reg_name now renamed in the database, every XiangShan register-file spec translates to generate_ram. Tests: the two-write RAM folded on Nangate45 (2 folds) and asap7 (4 folds, banks, registered reads, hold mux), simulated against the behavioral model, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 3 + patches/0022-openroad-ram-bit-folds.patch | 454 ++++++++++++++++++ patches/0109-orfs-regfiles-generate-ram.patch | 119 ++++- test/regfile/sim/BUILD.bazel | 5 +- 4 files changed, 573 insertions(+), 8 deletions(-) create mode 100644 patches/0022-openroad-ram-bit-folds.patch diff --git a/MODULE.bazel b/MODULE.bazel index b2b7cfd4f..6de4fb933 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -166,6 +166,9 @@ archive_override( # 0021: generate_ram -decoder word, a balanced AND2 tree per word. # On 0020 (OpenROAD #11669); not upstreamed. "//patches:0021-openroad-ram-word-decoder.patch", + # 0022: generate_ram -bit_folds, a word's slices in rows. On 0021 + # (OpenROAD #11669); not upstreamed. + "//patches:0022-openroad-ram-bit-folds.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0022-openroad-ram-bit-folds.patch b/patches/0022-openroad-ram-bit-folds.patch new file mode 100644 index 000000000..71522efe6 --- /dev/null +++ b/patches/0022-openroad-ram-bit-folds.patch @@ -0,0 +1,454 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -bit_folds, a word's slices in rows + +-bit_folds k lays a word's mask slices (-mask_size word/k) in k rows +instead of side by side. generate_ram puts a word in one row, a bit's +cells side by side, so a wide word with many ports is a long thin +array: XiangShan's integer register file, 64 bits, 12 read and 9 write +ports, came out 1458 x 31 um. With folds the decoder, select-buffer and +address-inverter columns take k rows a word, and a column's input +buffers share its cell. A folded word is written whole: one write +enable a port, and the word's write logic (enables, priority, hold, +clock gate, reset tie, select inverters) built in its first fold and +shared by the others. Not with -use_latch or the row decoder's column +mux. + +The twelfth of the generate_regfile features carried onto generate_ram; +see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index d253b23818..5400b8b04a 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -123,7 +123,8 @@ class RamGen + const std::string& pin_layer = "", + const std::string& cells = "", + const std::string& name = "", +- const std::string& decoder = "row"); ++ const std::string& decoder = "row", ++ int bit_folds = 1); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -385,6 +386,28 @@ class RamGen + // a row; each pin where its connections land, on pin_layer_'s tracks + bool periphery_unplaced_{false}; + std::string ram_name_; // the block's and the behavioral model's name ++ // -bit_folds k: a word's mask slices in k rows instead of side by side, ++ // so a wide word with many ports is as tall as it is wide; every ++ // column is k rows a word ++ int bit_folds_{1}; ++ int slice_width_{0}; // a slice's columns: its bits, and its select ++ // with -bit_folds a word is written whole: its write logic (enables, ++ // priority, hold, clock gate, reset tie, select inverters) built in its ++ // first fold and shared by the others, keyed (row, word in the row) ++ struct WordWrite ++ { ++ odb::dbNet* we{nullptr}; ++ odb::dbNet* hold{nullptr}; ++ odb::dbNet* gclock{nullptr}; ++ odb::dbNet* reset_off{nullptr}; ++ std::vector take; ++ std::vector select_b; ++ }; ++ std::map, WordWrite> word_write_; ++ int sliceOffset(int slice) const ++ { ++ return bit_folds_ > 1 ? 0 : slice * slice_width_; ++ } + std::string pin_layer_; + bool marking_periphery_{false}; + Cell* periphery_cell_{nullptr}; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index b5a03e9315..9b47ad7032 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -349,18 +349,25 @@ void RamGen::makeSlice(const int slice_idx, + } + } + ram_grid_.addCell(std::move(cell), +- slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) ++ sliceOffset(slice_idx) + + local_bit * column_mux_ratio + word_idx); + } + ram_grid_.addCell(nullptr, +- slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) ++ sliceOffset(slice_idx) + + mask_size * column_mux_ratio + word_idx); + return; + } + + int r_total = rw_ports + r_ports; ++ // -bit_folds: the word's first fold builds its write logic, the others ++ // share it ++ const bool shared = bit_folds_ > 1 && slice_idx > 0; ++ WordWrite& word_write = word_write_[{row_idx, word_idx}]; ++ + vector select_b_nets(r_total); +- if (and_or_read_) { ++ if (shared) { ++ select_b_nets = word_write.select_b; ++ } else if (and_or_read_) { + // the AND-OR trees read the true selects + } else if (column_mux_ratio == 1 || banked_) { + for (int i = 0; i < r_total; ++i) { +@@ -374,13 +381,15 @@ void RamGen::makeSlice(const int slice_idx, + + // the flops' clock: the word's gated clock, or with -write_style mux + // the clock itself +- auto gclock_net = write_mux_ ? clock : makeNet(prefix, "gclock"); +- auto we_net = makeNet(prefix, "we"); ++ auto gclock_net = shared ? word_write.gclock ++ : write_mux_ ? clock ++ : makeNet(prefix, "gclock"); ++ auto we_net = shared ? word_write.we : makeNet(prefix, "we"); + auto sel_cell = std::make_unique(); + periphery_cell_ = sel_cell.get(); // each word's select cell + // -write_style mux: the word's hold, where it is not written +- dbNet* hold = nullptr; +- if (write_mux_) { ++ dbNet* hold = shared ? word_write.hold : nullptr; ++ if (write_mux_ && !shared) { + hold = makeNet(prefix, "hold"); + makeInst(sel_cell.get(), + prefix, +@@ -430,8 +439,8 @@ void RamGen::makeSlice(const int slice_idx, + }; + + // -reset_value: one tie per word slice holds the flops' unused pins off +- dbNet* reset_off = nullptr; +- if (reset_port_) { ++ dbNet* reset_off = shared ? word_write.reset_off : nullptr; ++ if (reset_port_ && !shared) { + reset_off = makeNet(prefix, "reset_off"); + makeInst(sel_cell.get(), + prefix, +@@ -446,7 +455,9 @@ void RamGen::makeSlice(const int slice_idx, + // last port wins, as in the behavioral model. The clock gate opens for + // any of them. + vector take(num_write); +- if (num_write > 1) { ++ if (shared) { ++ take = word_write.take; ++ } else if (num_write > 1) { + vector we(num_write); + for (int w = 0; w < num_write; ++w) { + we[w] = makeNet(prefix, fmt::format("we{}", w)); +@@ -490,6 +501,10 @@ void RamGen::makeSlice(const int slice_idx, + } + } + ++ if (!shared) { ++ word_write = {we_net, hold, gclock_net, reset_off, take, select_b_nets}; ++ } ++ + for (int local_bit = 0; local_bit < mask_size; ++local_bit) { + auto name = fmt::format("{}.bit{}", prefix, start_bit_idx + local_bit); + vector outs(r_total); +@@ -606,13 +621,13 @@ void RamGen::makeSlice(const int slice_idx, + } + } + +- int bit_col = slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) ++ int bit_col = sliceOffset(slice_idx) + + local_bit * column_mux_ratio + word_idx; + ram_grid_.addCell(std::move(bit_cell), bit_col); + } + + // Make clock gate (with -write_style mux, none: the flops hold by mux) +- if (!write_mux_) { ++ if (!write_mux_ && !shared) { + makeInst(sel_cell.get(), + prefix, + "cg", +@@ -640,7 +655,7 @@ void RamGen::makeSlice(const int slice_idx, + // Make clock and + // this AND gate needs to be fed a net created by a decoder + // adding any net will automatically connect with any port +- if (num_write == 1) { ++ if (num_write == 1 && !shared) { + makeInst(sel_cell.get(), + prefix, + "gcand", +@@ -651,7 +666,7 @@ void RamGen::makeSlice(const int slice_idx, + } + + // Make select inverters +- if (create_select_inv && !and_or_read_) { ++ if (create_select_inv && !and_or_read_ && !shared) { + for (int i = 0; i < r_total; ++i) { + if (selects[num_write + i] == nullptr) { + continue; // a banked read port's other banks +@@ -665,9 +680,10 @@ void RamGen::makeSlice(const int slice_idx, + } + } + +- int sel_col = slice_idx * (mask_size * column_mux_ratio + column_mux_ratio) ++ int sel_col = sliceOffset(slice_idx) + + mask_size * column_mux_ratio + word_idx; +- ram_grid_.addCell(std::move(sel_cell), sel_col); ++ // a fold sharing its word's logic has an empty select cell ++ ram_grid_.addCell(shared ? nullptr : std::move(sel_cell), sel_col); + } + + // Note: For column_mux_ratio > 1, creates one shared select_b net per row and +@@ -703,7 +719,8 @@ void RamGen::makeWord(const int slices_per_word, + for (size_t w = 0; w < data_input.size(); ++w) { + slice_inputs.emplace_back(data_input[w].begin() + start_idx, + data_input[w].begin() + start_idx + mask_size); +- slice_enables.push_back(write_enable[w][slice]->getNet()); ++ slice_enables.push_back( ++ write_enable[w][bit_folds_ > 1 ? 0 : slice]->getNet()); + } + std::vector> slice_outputs; + slice_outputs.reserve(r_total); +@@ -789,6 +806,9 @@ void RamGen::makeDecoderColumn( + } + } + decoder_layout->addCell(std::move(word_cell)); ++ for (int f = 1; f < bit_folds_; ++f) { ++ decoder_layout->addCell(nullptr); // the word's other folds ++ } + } + marking_periphery_ = false; + ram_grid_.addLayout(std::move(decoder_layout)); +@@ -819,6 +839,9 @@ void RamGen::makeBufferColumn(const std::string& prefix, + {buffer_ports_[{PortRoleType::DataOut, 0}], select_nets[word]}}); + } + buffer_layout->addCell(std::move(buf_cell)); ++ for (int f = 1; f < bit_folds_; ++f) { ++ buffer_layout->addCell(nullptr); // the word's other folds ++ } + } + marking_periphery_ = false; + ram_grid_.addLayout(std::move(buffer_layout)); +@@ -876,6 +899,9 @@ void RamGen::makeWordDecoderColumn( + } + } + decoder_layout->addCell(std::move(row_cell)); ++ for (int f = 1; f < bit_folds_; ++f) { ++ decoder_layout->addCell(nullptr); // the word's other folds ++ } + } + marking_periphery_ = false; + ram_grid_.addLayout(std::move(decoder_layout)); +@@ -1916,7 +1942,8 @@ void RamGen::generate(const int mask_size, + const std::string& pin_layer, + const std::string& cells, + const std::string& name, +- const std::string& decoder) ++ const std::string& decoder, ++ const int bit_folds) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1980,6 +2007,23 @@ void RamGen::generate(const int mask_size, + // the words in a row: the column mux's, or the banks side by side + const int column_mux_ratio = banked_ ? bank_columns_ : column_mux_ratio_arg; + words_per_row_ = column_mux_ratio; ++ bit_folds_ = std::max(bit_folds, 1); ++ slice_width_ = mask_size * column_mux_ratio + column_mux_ratio; ++ if (bit_folds_ > 1) { ++ if (word_size / mask_size != bit_folds_) { ++ logger_->error(RAM, ++ 83, ++ "-bit_folds {} needs -mask_size {}: a fold is a slice.", ++ bit_folds_, ++ word_size / bit_folds_); ++ } ++ if (use_latch || (!banked_ && column_mux_ratio > 1)) { ++ logger_->error(RAM, ++ 84, ++ "-bit_folds is not supported with -use_latch or the row " ++ "decoder's -column_mux_ratio above 1."); ++ } ++ } + if (num_words / column_mux_ratio == 1) { + logger_->error(RAM, 42, "1-row RAMs are not supported."); + } +@@ -2039,6 +2083,7 @@ void RamGen::generate(const int mask_size, + storage_inverted_ = false; + storage_nets_.clear(); + tree_nodes_.clear(); ++ word_write_.clear(); + storage_cell_ = storage_cell; + tristate_cell_ = tristate_cell; + inv_cell_ = inv_cell; +@@ -2208,7 +2253,8 @@ void RamGen::generate(const int mask_size, + + // mux layout columns + per-port buffer/decoder columns + inverter columns + int col_cell_count +- = slices_per_word * (mask_size * column_mux_ratio + column_mux_ratio); ++ = (bit_folds_ > 1 ? 1 : slices_per_word) ++ * (mask_size * column_mux_ratio + column_mux_ratio); + ram_grid_.setNumLayouts(col_cell_count); + + auto clock = makeBTerm("clk", dbIoType::INPUT); +@@ -2231,7 +2277,9 @@ void RamGen::generate(const int mask_size, + num_write, vector(slices_per_word, nullptr)); + for (int w = 0; w < num_write; ++w) { + const std::string we = num_write == 1 ? "we" : fmt::format("we{}", w); +- for (int slice = 0; slice < slices_per_word; ++slice) { ++ // with -bit_folds a word is written whole: one enable a port ++ for (int slice = 0; slice < (bit_folds_ > 1 ? 1 : slices_per_word); ++ ++slice) { + write_enable[w][slice] + = makeBTerm(fmt::format("{}[{}]", we, slice), dbIoType::INPUT); + } +@@ -2763,10 +2811,17 @@ void RamGen::generate(const int mask_size, + } + } + ++ // the input buffers, a cell a column (with -bit_folds, every fold's ++ // buffer of the column in it) ++ std::map> buffer_cells; + for (int slice = 0; slice < slices_per_word; ++slice) { + for (int bit = 0; bit < mask_size; ++bit) { + int bit_idx = bit + slice * mask_size; +- auto buffer_grid_cell = std::make_unique(); ++ int buf_col = sliceOffset(slice) + bit * column_mux_ratio; ++ auto& buffer_grid_cell = buffer_cells[buf_col]; ++ if (!buffer_grid_cell) { ++ buffer_grid_cell = std::make_unique(); ++ } + marking_periphery_ = true; // the input buffers + for (int w = 0; w < num_write; ++w) { + makeInst(buffer_grid_cell.get(), +@@ -2779,11 +2834,11 @@ void RamGen::generate(const int mask_size, + D_nets[w][bit_idx]}}); + } + marking_periphery_ = false; +- int buf_col = slice * (mask_size * column_mux_ratio + column_mux_ratio) +- + bit * column_mux_ratio; +- ram_grid_.addCell(std::move(buffer_grid_cell), buf_col); + } + } ++ for (auto& [buf_col, cell] : buffer_cells) { ++ ram_grid_.addCell(std::move(cell), buf_col); ++ } + + // indices for creating buffers + int r_buf_idx = 0; +@@ -2834,7 +2889,7 @@ void RamGen::generate(const int mask_size, + for (int col = 0; col < inv_col_count; ++col) { + int start_port = col * ports_per_col; + int end_port = std::min(start_port + ports_per_col, total_ports); +- ram_grid_.addLayout(makeInverterColumn(num_rows, ++ ram_grid_.addLayout(makeInverterColumn(num_rows * bit_folds_, + num_row_bits, + start_port, + end_port, +@@ -2933,7 +2988,7 @@ void RamGen::generate(const int mask_size, + } + // // One extra row at the top for placing input buffers, one extra row for + // // negative latches if use latch-based ram +- const int num_rows_grid = num_rows + 1 + (use_latch_ ? 1 : 0); ++ const int num_rows_grid = num_rows * bit_folds_ + 1 + (use_latch_ ? 1 : 0); + + // auto cell_inv_layout = std::make_unique(odb::vertical); + // // check for AND gate, specific case for 2 words +@@ -3042,9 +3097,10 @@ void RamGen::generate(const int mask_size, + unplacePeriphery(); + } + ++ // with -bit_folds a word is written whole: one slice to the model + writeBehavioralVerilog(behavioral_verilog_filename_, +- slices_per_word, +- mask_size, ++ bit_folds_ > 1 ? 1 : slices_per_word, ++ bit_folds_ > 1 ? word_size : mask_size, + num_words, + rw_ports, + r_ports, +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 6fdfcf5eda..4aaa60f0f3 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -56,7 +56,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* pin_layer, + const char* cells, + const char* name, +- const char* decoder) ++ const char* decoder, ++ const int bit_folds) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -111,7 +112,7 @@ generate_ram_netlist_cmd(int mask_size, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, + read_latency, write_style, periphery, pin_layer, cells, +- name, decoder); ++ name, decoder, bit_folds); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 1b056eaabf..db7e1d06c8 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -19,6 +19,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-cells {role master ...}] + [-name name] + [-decoder row|word] ++ [-bit_folds count] + [-zero_word word] + [-reset_value value] + [-banks count] +@@ -32,6 +33,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-cells {role master ...}] + [-name name] + [-decoder row|word] ++ [-bit_folds count] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -46,7 +48,7 @@ proc generate_ram_netlist { args } { + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -periphery -pin_layer -cells -name -decoder } flags {} ++ -periphery -pin_layer -cells -name -decoder -bit_folds } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -221,6 +223,11 @@ proc generate_ram_netlist { args } { + # The address decoders: row, a decoder per row (an AND2 chain), the + # column mux selecting within it; or word, a balanced AND2 tree over + # each word's whole address. ++ # A word's mask slices in this many rows instead of side by side. ++ set bit_folds 1 ++ if { [info exists keys(-bit_folds)] } { ++ set bit_folds $keys(-bit_folds) ++ } + set decoder row + if { [info exists keys(-decoder)] } { + set decoder $keys(-decoder) +@@ -262,7 +269,7 @@ proc generate_ram_netlist { args } { + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ + $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name \ +- $decoder ++ $decoder $bit_folds + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -298,7 +305,7 @@ proc generate_ram { args } { + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -cells -name -decoder } flags {} ++ -cells -name -decoder -bit_folds } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -348,7 +355,7 @@ proc generate_ram { args } { + } + + foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -cells -name -decoder} { ++ -cells -name -decoder -bit_folds} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } diff --git a/patches/0109-orfs-regfiles-generate-ram.patch b/patches/0109-orfs-regfiles-generate-ram.patch index 2cad1b106..1566ccc03 100644 --- a/patches/0109-orfs-regfiles-generate-ram.patch +++ b/patches/0109-orfs-regfiles-generate-ram.patch @@ -58,7 +58,7 @@ diff --git a/flow/scripts/memories/regfile_ram.py b/flow/scripts/memories/regfil new file mode 100644 --- /dev/null +++ b/flow/scripts/memories/regfile_ram.py -@@ -0,0 +1,391 @@ +@@ -0,0 +1,496 @@ +"""AUTO_MEMORIES_REGFILES through OpenROAD's generate_ram. + +A register-file spec (the keys generate_regfile reads) is translated to @@ -72,10 +72,12 @@ new file mode 100644 +- inlined: its netlist follows the wrapper in .v; +- mode netlist: a macro with its periphery unplaced, which + regfile_dissolve.tcl dissolves after macro placement from -+ _ram.v (one instance a line) and _ram.place; -+A spec using a key generate_ram does not have yet (flop names for -+equivalence checking, folded bits, the periphery as Verilog), or kept -+as a macro to the end, is left to generate_regfile; supported() says ++ _ram.v (one instance a line) and _ram.place. ++ ++The flops take the RTL's names where the spec gives them (store_name, ++read_reg_name), for equivalence checking: renamed in the database from ++generate_ram's own. A spec with the periphery as Verilog, or kept as a ++macro to the end, is left to generate_regfile for now; supported() says +which. +""" + @@ -88,7 +90,7 @@ new file mode 100644 +from pathlib import Path + +# keys generate_ram has no counterpart for yet -+UNSUPPORTED = {"store_name", "read_reg_name", "bit_folds", "pin_track", "lib"} ++UNSUPPORTED = {"pin_track", "lib"} + +# a spec's `cell ` roles, as generate_ram's -cells names them +CELL_ROLES = { @@ -154,6 +156,7 @@ new file mode 100644 + """generate_ram_netlist's options for the spec.""" + words = int(_one(lines, "words")) + bits = int(_one(lines, "bits")) ++ folds = int(_one(lines, "bit_folds", "1")) + cells = {line[1]: line[2] for line in lines if line[0] == "cell"} + async_reset = _values(lines, "async_reset") + storage = cells.get("flop_r" if async_reset else "flop") @@ -161,7 +164,7 @@ new file mode 100644 + "-name", + block, + "-mask_size", -+ str(bits), ++ str(bits // folds), + "-word_size", + str(bits), + "-num_words", @@ -178,6 +181,9 @@ new file mode 100644 + ] + if storage: + args += ["-storage_cell", storage] ++ if folds > 1: ++ # a word's bits in folds rows, a slice each ++ args += ["-bit_folds", str(folds)] + if _values(lines, "read_banked"): + args += ["-rb_ports", str(len(_values(lines, "read_banked")))] + for key in ("zero_word", "banks", "bank_columns", "bank_order", "read_latency"): @@ -286,6 +292,89 @@ new file mode 100644 +""" + + ++def _word_at(lines: list[list[str]], row: int, w: int) -> int: ++ """The word generate_ram (-decoder word) puts at (row, word in the ++ row): RamGen::wordAt.""" ++ words = int(_one(lines, "words")) ++ banks = int(_one(lines, "banks", "1")) ++ columns = int(_one(lines, "bank_columns", "1")) ++ per_bank = words // banks ++ bank = (row // per_bank) * columns + w ++ i = row % per_bank ++ if _one(lines, "bank_order", "contiguous") == "interleaved": ++ return i * banks + bank ++ return bank * per_bank + i ++ ++ ++def _renames(lines: list[list[str]]) -> list[tuple[str, str]]: ++ """generate_ram's flop names to the spec's store_name and ++ read_reg_name, as generate_regfile names them.""" ++ renames = [] ++ words = int(_one(lines, "words")) ++ bits = int(_one(lines, "bits")) ++ columns = int(_one(lines, "bank_columns", "1")) ++ store = _one(lines, "store_name") ++ per_fold = bits // int(_one(lines, "bit_folds", "1")) ++ if store: ++ for row in range(words // columns): ++ for w in range(columns): ++ word = _word_at(lines, row, w) ++ if word == int(_one(lines, "zero_word", "-1")): ++ continue ++ for bit in range(bits): ++ renames.append( ++ ( ++ f"storage_{row}_{w}_{bit // per_fold * per_fold}" ++ f".bit{bit}.bit", ++ store.replace("{word}", str(word)).replace( ++ "{bit}", str(bit) ++ ), ++ ) ++ ) ++ reg = _one(lines, "read_reg_name") ++ if reg and _one(lines, "read_latency", "0") != "0": ++ banks = int(_one(lines, "banks", "1")) ++ a = _address_bits(words) ++ ab = _address_bits(words // banks) ++ # generate_ram's ports: writes, then plain reads, then each banked ++ # read port's banks; the spec's read ports, plain and banked, in ++ # the order it lists them ++ first_read = len(_values(lines, "write")) ++ plain = len(_values(lines, "read")) ++ spec_port = 0 ++ plain_seen = 0 ++ banked_seen = 0 ++ for line in lines: ++ if line[0] == "read": ++ p = first_read + plain_seen ++ plain_seen += 1 ++ for i in range(a): ++ renames.append( ++ ( ++ f"decoder_p{p}.addr_reg_p{p}_a{i}", ++ reg.replace("{port}", str(spec_port)) ++ .replace("{bank}", "0") ++ .replace("{bit}", str(i)), ++ ) ++ ) ++ spec_port += 1 ++ elif line[0] == "read_banked": ++ for b in range((len(line) - 1) // 2): ++ p = first_read + plain + banked_seen * banks + b ++ for i in range(ab): ++ renames.append( ++ ( ++ f"decoder_p{p}.addr_reg_p{p}_a{i}", ++ reg.replace("{port}", str(spec_port)) ++ .replace("{bank}", str(b)) ++ .replace("{bit}", str(i)), ++ ) ++ ) ++ banked_seen += 1 ++ spec_port += 1 ++ return renames ++ ++ +def _module_ports(yosys_json: Path, module: str) -> dict[str, tuple[str, int]]: + """The RTL module's ports, name -> (direction, width), from the + design's yosys JSON; empty where it does not have the module.""" @@ -425,6 +514,22 @@ new file mode 100644 + subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(gen)]) + views = out_dir / f"{module}.views.tcl" + tcl = reads + f"read_db {out_dir / f'{block}.odb'}\n" ++ # the RTL's flop names, for equivalence checking ++ renames = _renames(lines) ++ if renames: ++ (out_dir / f"{block}.renames").write_text( ++ "".join(f"{{{old}}} {{{new}}}\n" for old, new in renames) ++ ) ++ tcl += ( ++ f"set f [open {out_dir / f'{block}.renames'} r]\n" ++ "while {[gets $f line] >= 0} {\n" ++ " lassign $line old new\n" ++ " set inst [[ord::get_db_block] findInst $old]\n" ++ ' if {$inst eq "NULL"} { error "regfile_ram: no $old to name $new" }\n' ++ " $inst rename $new\n" ++ "}\n" ++ "close $f\n" ++ ) + tcl += _VIEWS_TCL.format(out=out_dir, block=block) + if shape == "inline": + tcl += f"write_verilog {out_dir / f'{block}.netlist.v'}\n" diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 92c3b211f..962e80e45 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -163,7 +163,8 @@ ASAP7 = { # banked read port beside a plain one (patch 0016); and with registered # read addresses (patch 0017), on Q and QN flops; and holding words by a # mux per bit instead of a clock gate (patch 0018), and with its periphery -# left unplaced (patch 0019); and with cells given by role (patch 0020). +# left unplaced (patch 0019); with cells given by role (patch 0020); and a +# word's bits folded into rows (patch 0022). [ [ genrule( @@ -251,5 +252,7 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_rst_mux_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -write_style mux -reset_value 0xa5", "tb_ram_2w_rst", 8), ("ram_2w_unplaced_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -periphery unplaced -pin_layer M4", "tb_ram_2w", 8), ("ram_2w_cells_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -cells {inv INVx1_ASAP7_75t_R and2 AND2x2_ASAP7_75t_R buffer BUFx2_ASAP7_75t_R aoi22 AOI22x1_ASAP7_75t_R ao22 AO22x2_ASAP7_75t_R or2 OR2x2_ASAP7_75t_R nand2 NAND2x1_ASAP7_75t_R nor2 NOR2x1_ASAP7_75t_R} -name RAM8x8", "tb_ram_2w", 8), + ("ram_2w_folds", NANGATE45, "-storage_cell DFF_X1 -mask_size 4 -bit_folds 2 -decoder word", "tb_ram_2w", 8), + ("ram_2w_folds_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -mask_size 2 -bit_folds 4 -banks 4 -bank_columns 2 -bank_order interleaved -write_style mux -read_latency 1", "tb_ram_2w", 8), ] ] From 158e99b132ddc14b543328e877147dbaffebff9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 10:40:09 +0200 Subject: [PATCH 22/26] regfile: fold a register file that comes out a long strip (ORFS 0109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_regfile chose its rows per word itself; generate_ram puts a word in one row unless told. Where a spec names no bit_folds and the first generation comes out more than 8 times as wide as tall, the translation regenerates it folded into the power of two of rows nearest the square: XiangShan's IntRegFile, 1458 x 31 um in one row, 247 x 242 um in 8. A heuristic with a high bar: riscv32i's 55 x 9 um strip, 6 to 1, is the shape that sits under its FakeRAMs, so it stays; a spec names bit_folds to choose. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- patches/0109-orfs-regfiles-generate-ram.patch | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/patches/0109-orfs-regfiles-generate-ram.patch b/patches/0109-orfs-regfiles-generate-ram.patch index 1566ccc03..3ac0f1011 100644 --- a/patches/0109-orfs-regfiles-generate-ram.patch +++ b/patches/0109-orfs-regfiles-generate-ram.patch @@ -58,7 +58,7 @@ diff --git a/flow/scripts/memories/regfile_ram.py b/flow/scripts/memories/regfil new file mode 100644 --- /dev/null +++ b/flow/scripts/memories/regfile_ram.py -@@ -0,0 +1,496 @@ +@@ -0,0 +1,525 @@ +"""AUTO_MEMORIES_REGFILES through OpenROAD's generate_ram. + +A register-file spec (the keys generate_regfile reads) is translated to @@ -504,14 +504,43 @@ new file mode 100644 + raise SystemExit("regfile_ram: generate_ram needs LIB_FILES") + reads = "".join(f"read_liberty {lib}\n" for lib in libs) + gen = out_dir / f"{module}.generate.tcl" -+ gen.write_text( -+ reads -+ + "".join(f"read_lef {lef}\n" for lef in lefs) -+ + "generate_ram_netlist " -+ + " ".join(_args(lines, block, shape)) -+ + f"\nwrite_db {out_dir / f'{block}.odb'}\n" -+ ) -+ subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(gen)]) ++ outline = out_dir / f"{block}.outline" ++ ++ def build(spec_lines: list[list[str]]) -> tuple[float, float]: ++ gen.write_text( ++ reads ++ + "".join(f"read_lef {lef}\n" for lef in lefs) ++ + "generate_ram_netlist " ++ + " ".join(_args(spec_lines, block, shape)) ++ + f"\nwrite_db {out_dir / f'{block}.odb'}\n" ++ + "set die [[ord::get_db_block] getDieArea]\n" ++ + f"set f [open {outline} w]\n" ++ + "puts $f \"[$die dx] [$die dy]\"\n" ++ + "close $f\n" ++ ) ++ subprocess.check_call( ++ [openroad, "-exit", "-no_init", "-no_splash", str(gen)] ++ ) ++ width, height = outline.read_text().split() ++ return float(width), float(height) ++ ++ width, height = build(lines) ++ # generate_regfile chose its rows per word itself: where the spec names ++ # no folds and a word in one row came out more than 8 times as wide as ++ # tall (XiangShan's IntRegFile, 12 reads and 9 writes, 48), fold it ++ # into the power of two of rows nearest the square. A heuristic: a ++ # strip of a few to one can be the shape that fits (riscv32i's, 6, sits ++ # under its FakeRAMs), so a spec names bit_folds to choose. ++ bits = int(_one(lines, "bits")) ++ if not _values(lines, "bit_folds") and width > 8 * height: ++ folds = 1 ++ while folds * 2 <= bits and bits % (folds * 2) == 0 and ( ++ folds * 2 ++ ) ** 2 <= 2 * width / height: ++ folds *= 2 ++ if folds > 1: ++ lines = lines + [["bit_folds", str(folds)]] ++ build(lines) + views = out_dir / f"{module}.views.tcl" + tcl = reads + f"read_db {out_dir / f'{block}.odb'}\n" + # the RTL's flop names, for equivalence checking From c7b0bbb30c659fb56234a71ca4166c4bd47e579c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 11:00:38 +0200 Subject: [PATCH 23/26] ram: -bit_folds stacks a column's input buffers a row a fold (patch 0022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With every fold's input buffers in one cell a column, IntRegFile's 72 buffers a column (8 folds, 9 write ports) set its width: 16 columns pitched 246.7 um wide around 182.3 um of widest placed cells, fill 58 %. A row a fold for them, above the words, gives the columns back to the bit cells: IntRegFile folded 8 is 182.3 x 242.2 um, 44 153 um2, below its 44 497 um2 unfolded, where folding had cost 34 %. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- patches/0022-openroad-ram-bit-folds.patch | 33 +++++++++++++---------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/patches/0022-openroad-ram-bit-folds.patch b/patches/0022-openroad-ram-bit-folds.patch index 71522efe6..63b1dd7fd 100644 --- a/patches/0022-openroad-ram-bit-folds.patch +++ b/patches/0022-openroad-ram-bit-folds.patch @@ -7,7 +7,8 @@ cells side by side, so a wide word with many ports is a long thin array: XiangShan's integer register file, 64 bits, 12 read and 9 write ports, came out 1458 x 31 um. With folds the decoder, select-buffer and address-inverter columns take k rows a word, and a column's input -buffers share its cell. A folded word is written whole: one write +buffers stack a row a fold above the words, so a wide word's buffers do +not set the column's width. A folded word is written whole: one write enable a port, and the word's write logic (enables, priority, hold, clock gate, reset tie, select inverters) built in its first fold and shared by the others. Not with -use_latch or the row decoder's column @@ -61,7 +62,7 @@ index d253b23818..5400b8b04a 100644 bool marking_periphery_{false}; Cell* periphery_cell_{nullptr}; diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp -index b5a03e9315..9b47ad7032 100644 +index b5a03e9315..cf48730c73 100644 --- a/src/ram/src/ram.cpp +++ b/src/ram/src/ram.cpp @@ -349,18 +349,25 @@ void RamGen::makeSlice(const int slice_idx, @@ -296,26 +297,28 @@ index b5a03e9315..9b47ad7032 100644 write_enable[w][slice] = makeBTerm(fmt::format("{}[{}]", we, slice), dbIoType::INPUT); } -@@ -2763,10 +2811,17 @@ void RamGen::generate(const int mask_size, +@@ -2763,10 +2811,19 @@ void RamGen::generate(const int mask_size, } } -+ // the input buffers, a cell a column (with -bit_folds, every fold's -+ // buffer of the column in it) -+ std::map> buffer_cells; ++ // the input buffers, a cell a column and slice: with -bit_folds a ++ // column's folds stack theirs in k rows, so the buffers of a wide word ++ // do not set the column's width ++ std::map, std::unique_ptr> buffer_cells; for (int slice = 0; slice < slices_per_word; ++slice) { for (int bit = 0; bit < mask_size; ++bit) { int bit_idx = bit + slice * mask_size; - auto buffer_grid_cell = std::make_unique(); + int buf_col = sliceOffset(slice) + bit * column_mux_ratio; -+ auto& buffer_grid_cell = buffer_cells[buf_col]; ++ auto& buffer_grid_cell ++ = buffer_cells[{buf_col, bit_folds_ > 1 ? slice : 0}]; + if (!buffer_grid_cell) { + buffer_grid_cell = std::make_unique(); + } marking_periphery_ = true; // the input buffers for (int w = 0; w < num_write; ++w) { makeInst(buffer_grid_cell.get(), -@@ -2779,11 +2834,11 @@ void RamGen::generate(const int mask_size, +@@ -2779,11 +2836,11 @@ void RamGen::generate(const int mask_size, D_nets[w][bit_idx]}}); } marking_periphery_ = false; @@ -324,13 +327,13 @@ index b5a03e9315..9b47ad7032 100644 - ram_grid_.addCell(std::move(buffer_grid_cell), buf_col); } } -+ for (auto& [buf_col, cell] : buffer_cells) { -+ ram_grid_.addCell(std::move(cell), buf_col); ++ for (auto& [key, cell] : buffer_cells) { ++ ram_grid_.addCell(std::move(cell), key.first); + } // indices for creating buffers int r_buf_idx = 0; -@@ -2834,7 +2889,7 @@ void RamGen::generate(const int mask_size, +@@ -2834,7 +2891,7 @@ void RamGen::generate(const int mask_size, for (int col = 0; col < inv_col_count; ++col) { int start_port = col * ports_per_col; int end_port = std::min(start_port + ports_per_col, total_ports); @@ -339,16 +342,18 @@ index b5a03e9315..9b47ad7032 100644 num_row_bits, start_port, end_port, -@@ -2933,7 +2988,7 @@ void RamGen::generate(const int mask_size, +@@ -2933,7 +2990,9 @@ void RamGen::generate(const int mask_size, } // // One extra row at the top for placing input buffers, one extra row for // // negative latches if use latch-based ram - const int num_rows_grid = num_rows + 1 + (use_latch_ ? 1 : 0); -+ const int num_rows_grid = num_rows * bit_folds_ + 1 + (use_latch_ ? 1 : 0); ++ // the words' rows, then the input buffers' (a row, or one a fold) ++ const int num_rows_grid ++ = num_rows * bit_folds_ + bit_folds_ + (use_latch_ ? 1 : 0); // auto cell_inv_layout = std::make_unique(odb::vertical); // // check for AND gate, specific case for 2 words -@@ -3042,9 +3097,10 @@ void RamGen::generate(const int mask_size, +@@ -3042,9 +3101,10 @@ void RamGen::generate(const int mask_size, unplacePeriphery(); } From 77afe219ec3e79d62b22c9963453c0894f524c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 11:12:32 +0200 Subject: [PATCH 24/26] ram: generate_ram_netlist -periphery verilog (patch 0023; ORFS 0109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -periphery verilog makes the block the core alone, _core, and writes the periphery as a Verilog module around it (-wrapper_verilog): its logic cells as assigns of their liberty functions, its clock gates, flops and ties as instances. A net the core shares with the periphery becomes a core port, renamed to a Verilog and liberty identifier, its net with it: the netlist names a port's net by the port. ORFS 0109 translates the spec's periphery verilog: the macro, or the inlined core, is _ram_core inside generate_ram's periphery module and the RTL's wrapper; the address registers keep generate_ram's names there. riscv32i, global route, 950 ps clock, periphery as Verilog: shape generate_regfile generate_ram inlined, 62 % 3516 um2, 938 ps 3452 um2, 951 ps netlist, 55 %, 2 um ch. 4287 um2, 940 ps 3999 um2, 933 ps Tests: the two-write RAM with its periphery as Verilog simulated on Nangate45 (tristates, clock gates) and asap7 (AND-OR, banks, hold mux) against the behavioral model, no mismatch. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 4 + .../0023-openroad-ram-periphery-verilog.patch | 404 ++++++++++++++++++ patches/0109-orfs-regfiles-generate-ram.patch | 65 ++- test/regfile/sim/BUILD.bazel | 8 +- 4 files changed, 464 insertions(+), 17 deletions(-) create mode 100644 patches/0023-openroad-ram-periphery-verilog.patch diff --git a/MODULE.bazel b/MODULE.bazel index 6de4fb933..ad1b4ed64 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -169,6 +169,10 @@ archive_override( # 0022: generate_ram -bit_folds, a word's slices in rows. On 0021 # (OpenROAD #11669); not upstreamed. "//patches:0022-openroad-ram-bit-folds.patch", + # 0023: generate_ram_netlist -periphery verilog, the core a block of + # its own and its periphery a Verilog wrapper. On 0022 (OpenROAD + # #11669); not upstreamed. + "//patches:0023-openroad-ram-periphery-verilog.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/patches/0023-openroad-ram-periphery-verilog.patch b/patches/0023-openroad-ram-periphery-verilog.patch new file mode 100644 index 000000000..720a461f7 --- /dev/null +++ b/patches/0023-openroad-ram-periphery-verilog.patch @@ -0,0 +1,404 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram_netlist -periphery verilog + +-periphery verilog makes the block the core alone, _core, and +writes the periphery to -wrapper_verilog as a module around an +instance of it: the periphery's logic cells as assigns of their liberty +functions, for synthesis to map with the parent's logic, and its other +cells (clock gates, flops, ties) as instances. A net the core shares +with the periphery becomes a core port; a port only the periphery uses +leaves the core. The core is then outlined and pinned as with +-periphery unplaced. An option beside generator-built periphery, not a +replacement: which is better depends on how the array is integrated. + +The fourteenth of the generate_regfile features carried onto +generate_ram; see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 5400b8b04a..2d9b7181d2 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -124,7 +124,8 @@ class RamGen + const std::string& cells = "", + const std::string& name = "", + const std::string& decoder = "row", +- int bit_folds = 1); ++ int bit_folds = 1, ++ const std::string& wrapper_verilog = ""); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -413,6 +414,15 @@ class RamGen + Cell* periphery_cell_{nullptr}; + std::vector periphery_insts_; + void unplacePeriphery(); ++ // -periphery verilog: the periphery leaves the block, which becomes the ++ // core alone (_core), for a wrapper module in Verilog written to ++ // wrapper_verilog_: the periphery's logic cells as assigns of their ++ // liberty functions, its other cells (clock gates, flops, ties) as ++ // instances, around an instance of the core. A net the core shares ++ // with the periphery becomes a core port. ++ bool periphery_verilog_{false}; ++ std::string wrapper_verilog_; ++ void splitPeriphery(); + odb::dbMaster* addr_flop_cell_{nullptr}; + std::string addr_flop_d_, addr_flop_clk_, addr_flop_q_; + bool addr_flop_inverted_{false}; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index cf48730c73..7b670b6da9 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1943,7 +1944,8 @@ void RamGen::generate(const int mask_size, + const std::string& cells, + const std::string& name, + const std::string& decoder, +- const int bit_folds) ++ const int bit_folds, ++ const std::string& wrapper_verilog) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -1976,7 +1978,13 @@ void RamGen::generate(const int mask_size, + rb_ports_ = rb_ports; + read_latency_ = read_latency; + write_mux_ = write_style == "mux"; +- periphery_unplaced_ = periphery == "unplaced"; ++ periphery_verilog_ = periphery == "verilog"; ++ periphery_unplaced_ = periphery == "unplaced" || periphery_verilog_; ++ wrapper_verilog_ = wrapper_verilog; ++ if (periphery_verilog_ && wrapper_verilog_.empty()) { ++ logger_->error( ++ RAM, 85, "-periphery verilog needs -wrapper_verilog, its file."); ++ } + pin_layer_ = pin_layer; + periphery_insts_.clear(); + marking_periphery_ = false; +@@ -2231,7 +2239,10 @@ void RamGen::generate(const int mask_size, + + block_ = chip->getBlock(); + if (!block_) { +- block_ = odb::dbBlock::create(chip, ram_name.c_str()); ++ // -periphery verilog: the block is the core, the wrapper the name ++ const std::string block_name ++ = periphery_verilog_ ? ram_name + "_core" : ram_name; ++ block_ = odb::dbBlock::create(chip, block_name.c_str()); + } + + // One column per bit plus one select/control column per slice, +@@ -3118,8 +3129,235 @@ void RamGen::generate(const int mask_size, + // (those of the periphery too, while they are still placed), on the pin + // layer's track grid inside the outline: these pins are for a macro + // placer to orient the core by, never routed. ++// A liberty function as a Verilog expression, its pins by their nets. ++static std::string verilogExpr( ++ const sta::FuncExpr* f, ++ const std::map& nets) ++{ ++ if (f == nullptr) { ++ return "1'b0"; ++ } ++ switch (f->op()) { ++ case sta::FuncExpr::Op::port: { ++ auto it = nets.find(f->port()->name()); ++ return it == nets.end() ? "1'b0" : it->second; ++ } ++ case sta::FuncExpr::Op::not_: ++ return "~(" + verilogExpr(f->left(), nets) + ")"; ++ case sta::FuncExpr::Op::and_: ++ return "(" + verilogExpr(f->left(), nets) + " & " ++ + verilogExpr(f->right(), nets) + ")"; ++ case sta::FuncExpr::Op::or_: ++ return "(" + verilogExpr(f->left(), nets) + " | " ++ + verilogExpr(f->right(), nets) + ")"; ++ case sta::FuncExpr::Op::xor_: ++ return "(" + verilogExpr(f->left(), nets) + " ^ " ++ + verilogExpr(f->right(), nets) + ")"; ++ case sta::FuncExpr::Op::one: ++ return "1'b1"; ++ default: ++ return "1'b0"; ++ } ++} ++ ++// Ports as Verilog declarations, `name[i]` grouped into buses. ++static std::vector> verilogPorts( ++ const std::vector>& ports) ++{ ++ std::map> buses; ++ std::vector order; ++ for (const auto& [name, io] : ports) { ++ std::string base = name; ++ int index = -1; ++ const auto lb = name.rfind('['); ++ if (lb != std::string::npos && name.back() == ']') { ++ base = name.substr(0, lb); ++ index = std::stoi(name.substr(lb + 1, name.size() - lb - 2)); ++ } ++ if (buses.find(base) == buses.end()) { ++ order.push_back(base); ++ buses[base] = {io == odb::dbIoType::INPUT ? "input" : "output", -1}; ++ } ++ buses[base].second = std::max(buses[base].second, index); ++ } ++ std::vector> decls; ++ for (const auto& base : order) { ++ const auto& [dir, hi] = buses[base]; ++ decls.emplace_back( ++ base, ++ hi < 0 ? dir + " " + base ++ : fmt::format("{} [{}:0] {}", dir, hi, base)); ++ } ++ return decls; ++} ++ ++void RamGen::splitPeriphery() ++{ ++ std::set periphery; // by id: odb objects have no order ++ for (dbInst* inst : periphery_insts_) { ++ periphery.insert(inst->getId()); ++ } ++ auto ref = [](dbNet* n) { ++ return n->getBTerms().begin() != n->getBTerms().end() ++ ? std::string((*n->getBTerms().begin())->getName()) ++ : "\\" + n->getName() + " "; ++ }; ++ std::vector> ports; ++ for (dbBTerm* t : block_->getBTerms()) { ++ ports.emplace_back(t->getName(), t->getIoType()); ++ } ++ std::vector wires; ++ std::vector dropped; ++ std::vector> shared; ++ for (dbNet* n : block_->getNets()) { ++ if (n->getSigType() == odb::dbSigType::POWER ++ || n->getSigType() == odb::dbSigType::GROUND) { ++ continue; ++ } ++ bool in_periphery = false; ++ bool in_core = false; ++ bool periphery_drives = false; ++ for (odb::dbITerm* it : n->getITerms()) { ++ const bool p = periphery.count(it->getInst()->getId()) > 0; ++ in_periphery |= p; ++ in_core |= !p; ++ periphery_drives |= p && it->getIoType() == odb::dbIoType::OUTPUT; ++ } ++ if (n->getBTerms().begin() != n->getBTerms().end()) { ++ if (!in_core) { ++ for (dbBTerm* t : n->getBTerms()) { ++ dropped.push_back(t); ++ } ++ } ++ continue; ++ } ++ if (in_periphery) { ++ wires.push_back(ref(n)); ++ } ++ if (in_periphery && in_core) { ++ shared.emplace_back( ++ n, periphery_drives ? odb::dbIoType::INPUT : odb::dbIoType::OUTPUT); ++ } ++ } ++ // the wrapper: the periphery's cells, before they go ++ std::ostringstream body; ++ for (dbInst* inst : periphery_insts_) { ++ std::map nets; ++ std::vector> conns; ++ for (odb::dbITerm* it : inst->getITerms()) { ++ dbNet* n = it->getNet(); ++ if (n == nullptr || n->getSigType() == odb::dbSigType::POWER ++ || n->getSigType() == odb::dbSigType::GROUND) { ++ continue; ++ } ++ nets[it->getMTerm()->getName()] = ref(n); ++ conns.emplace_back(it->getMTerm()->getName(), ref(n)); ++ } ++ // a logic cell, one output with a function, as an assign ++ auto liberty = network_->libertyCell(network_->dbToSta(inst->getMaster())); ++ sta::LibertyPort* out = nullptr; ++ int outputs = 0; ++ if (liberty && !liberty->hasSequentials() && !liberty->isClockGate()) { ++ std::unique_ptr it( ++ liberty->portIterator()); ++ while (it->hasNext()) { ++ auto port = it->next()->libertyPort(); ++ if (port && port->direction()->isAnyOutput()) { ++ ++outputs; ++ out = port; ++ } ++ } ++ } ++ if (outputs == 1 && out->function() && !out->direction()->isTristate() ++ && nets.count(out->name())) { ++ body << " assign " << nets[out->name()] << " = " ++ << verilogExpr(out->function(), nets) << "; // " ++ << inst->getName() << "\n"; ++ continue; ++ } ++ body << " " << inst->getMaster()->getName() << " \\" << inst->getName() ++ << " ("; ++ for (size_t i = 0; i < conns.size(); ++i) { ++ body << (i ? ", " : "") << "." << conns[i].first << "(" ++ << conns[i].second << ")"; ++ } ++ body << ");\n"; ++ } ++ // the core: its own ports kept, the shared nets new ones, named as a ++ // Verilog and liberty identifier (a net's name has dots and brackets) ++ std::map shared_ref; // core port -> wrapper net ++ for (auto& [n, io] : shared) { ++ std::string name = n->getName(); ++ for (char& c : name) { ++ if (!std::isalnum(static_cast(c)) && c != '_') { ++ c = '_'; ++ } ++ } ++ while (block_->findBTerm(name.c_str()) != nullptr ++ || (name != n->getName() ++ && block_->findNet(name.c_str()) != nullptr)) { ++ name += "_"; ++ } ++ shared_ref[name] = ref(n); ++ // a port's net goes by the port's name, as the netlist writes it ++ n->rename(name.c_str()); ++ dbBTerm* t = dbBTerm::create(n, name.c_str()); ++ t->setIoType(io); ++ t->setSigType(odb::dbSigType::SIGNAL); ++ } ++ for (dbBTerm* t : dropped) { ++ odb::dbBTerm::destroy(t); ++ } ++ for (dbInst* inst : periphery_insts_) { ++ dbInst::destroy(inst); ++ } ++ periphery_insts_.clear(); ++ std::vector empty; ++ for (dbNet* n : block_->getNets()) { ++ if (n->getITerms().empty() && n->getBTerms().empty()) { ++ empty.push_back(n); ++ } ++ } ++ for (dbNet* n : empty) { ++ dbNet::destroy(n); ++ } ++ std::vector> core_ports; ++ for (dbBTerm* t : block_->getBTerms()) { ++ core_ports.emplace_back(t->getName(), t->getIoType()); ++ } ++ std::ofstream out(wrapper_verilog_); ++ if (!out) { ++ logger_->error(RAM, 86, "Unable to open file {}", wrapper_verilog_); ++ } ++ const auto decls = verilogPorts(ports); ++ out << "// generate_ram's periphery around " << block_->getName() ++ << ", as Verilog\nmodule " << ram_name_ << " (\n"; ++ for (size_t i = 0; i < decls.size(); ++i) { ++ out << " " << decls[i].second << (i + 1 < decls.size() ? ",\n" : "\n"); ++ } ++ out << ");\n"; ++ for (const auto& w : wires) { ++ out << " wire " << w << ";\n"; ++ } ++ out << body.str(); ++ // the core by its ports: a bus of the module's own, a shared net bit by ++ // bit, by its name ++ const auto core_decls = verilogPorts(core_ports); ++ out << " " << block_->getName() << " core ("; ++ for (size_t i = 0; i < core_decls.size(); ++i) { ++ const std::string& p = core_decls[i].first; ++ auto net = shared_ref.find(p); ++ out << (i ? ", " : "") << "." << p << "(" ++ << (net == shared_ref.end() ? p : net->second) << ")"; ++ } ++ out << ");\nendmodule\n"; ++} ++ + void RamGen::unplacePeriphery() + { ++ if (periphery_verilog_) { ++ splitPeriphery(); ++ } + odb::dbTechLayer* layer + = db_->getTech()->findLayer(pin_layer_.c_str()); + if (layer == nullptr) { +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 4aaa60f0f3..d70a2aecda 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -57,7 +57,8 @@ generate_ram_netlist_cmd(int mask_size, + const char* cells, + const char* name, + const char* decoder, +- const int bit_folds) ++ const int bit_folds, ++ const char* wrapper_verilog) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -112,7 +113,7 @@ generate_ram_netlist_cmd(int mask_size, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, + read_latency, write_style, periphery, pin_layer, cells, +- name, decoder, bit_folds); ++ name, decoder, bit_folds, wrapper_verilog); + } + + void generate_regfile_cmd(const char* spec_path, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index db7e1d06c8..19b99d4205 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -28,7 +28,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] +- [-periphery placed|unplaced] ++ [-periphery placed|unplaced|verilog] ++ [-wrapper_verilog file] + [-pin_layer layer] + [-cells {role master ...}] + [-name name] +@@ -48,7 +49,7 @@ proc generate_ram_netlist { args } { + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style +- -periphery -pin_layer -cells -name -decoder -bit_folds } flags {} ++ -periphery -pin_layer -cells -name -decoder -bit_folds -wrapper_verilog } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -200,10 +201,14 @@ proc generate_ram_netlist { args } { + set periphery placed + if { [info exists keys(-periphery)] } { + set periphery $keys(-periphery) +- if { $periphery ni {placed unplaced} } { +- utl::error RAM 77 "-periphery is placed or unplaced, not $periphery." ++ if { $periphery ni {placed unplaced verilog} } { ++ utl::error RAM 77 "-periphery is placed, unplaced or verilog, not $periphery." + } + } ++ set wrapper_verilog "" ++ if { [info exists keys(-wrapper_verilog)] } { ++ set wrapper_verilog $keys(-wrapper_verilog) ++ } + set pin_layer "" + if { [info exists keys(-pin_layer)] } { + set pin_layer $keys(-pin_layer) +@@ -269,7 +274,7 @@ proc generate_ram_netlist { args } { + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ + $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name \ +- $decoder $bit_folds ++ $decoder $bit_folds $wrapper_verilog + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] diff --git a/patches/0109-orfs-regfiles-generate-ram.patch b/patches/0109-orfs-regfiles-generate-ram.patch index 3ac0f1011..5c9d934f7 100644 --- a/patches/0109-orfs-regfiles-generate-ram.patch +++ b/patches/0109-orfs-regfiles-generate-ram.patch @@ -58,7 +58,7 @@ diff --git a/flow/scripts/memories/regfile_ram.py b/flow/scripts/memories/regfil new file mode 100644 --- /dev/null +++ b/flow/scripts/memories/regfile_ram.py -@@ -0,0 +1,525 @@ +@@ -0,0 +1,558 @@ +"""AUTO_MEMORIES_REGFILES through OpenROAD's generate_ram. + +A register-file spec (the keys generate_regfile reads) is translated to @@ -76,9 +76,11 @@ new file mode 100644 + +The flops take the RTL's names where the spec gives them (store_name, +read_reg_name), for equivalence checking: renamed in the database from -+generate_ram's own. A spec with the periphery as Verilog, or kept as a -+macro to the end, is left to generate_regfile for now; supported() says -+which. ++generate_ram's own. With `periphery verilog` generate_ram writes the ++periphery as a Verilog module, _ram, around the core, ++_ram_core, which is then what is inlined or the macro. A ++register file kept as a macro to the end is left to generate_regfile ++for now; supported() says which. +""" + +from __future__ import annotations @@ -141,11 +143,7 @@ new file mode 100644 + which generate_ram_netlist does only with its periphery unplaced.""" + lines = parse(spec) + keys = {line[0] for line in lines} -+ return ( -+ not (keys & UNSUPPORTED) -+ and _one(lines, "periphery") != "verilog" -+ and shape != "macro" -+ ) ++ return not (keys & UNSUPPORTED) and shape != "macro" + + +def _address_bits(words: int) -> int: @@ -202,7 +200,9 @@ new file mode 100644 + ] + if roles: + args += ["-cells", "{" + " ".join(roles) + "}"] -+ if shape == "netlist": ++ if _one(lines, "periphery") == "verilog": ++ args += ["-periphery", "verilog", "-pin_layer", _one(lines, "pin_layer", "M4")] ++ elif shape == "netlist": + args += ["-periphery", "unplaced", "-pin_layer", _one(lines, "pin_layer", "M4")] + return args + @@ -332,7 +332,13 @@ new file mode 100644 + ) + ) + reg = _one(lines, "read_reg_name") -+ if reg and _one(lines, "read_latency", "0") != "0": ++ # (with the periphery as Verilog the address registers are in the ++ # wrapper, under generate_ram's names) ++ if ( ++ reg ++ and _one(lines, "read_latency", "0") != "0" ++ and _one(lines, "periphery") != "verilog" ++ ): + banks = int(_one(lines, "banks", "1")) + a = _address_bits(words) + ab = _address_bits(words // banks) @@ -487,6 +493,21 @@ new file mode 100644 + ) + + ++def _module_header_ports(verilog: str, module: str) -> dict[str, tuple[str, int]]: ++ """A module's ports, name -> (direction, width), from its header.""" ++ body = verilog[verilog.index(f"module {module} (") :] ++ body = body[: body.index(");")] ++ ports = {} ++ for line in body.splitlines(): ++ words = line.strip().rstrip(",").split() ++ if words and words[0] in ("input", "output"): ++ width = 1 ++ if len(words) == 3 and words[1].startswith("["): ++ width = int(words[1][1 : words[1].index(":")]) + 1 ++ ports[words[-1]] = (words[0], width) ++ return ports ++ ++ +def generate( + spec: Path, + module: str, @@ -498,7 +519,11 @@ new file mode 100644 + """Build the spec's RAM, shape inline, netlist or macro; return what + the flow lists: the block, and whether it is a macro and dissolves.""" + lines = parse(spec) -+ block = f"{module}_ram" ++ ram = f"{module}_ram" ++ # -periphery verilog: the block is the core, the periphery a module ++ verilog_periphery = _one(lines, "periphery") == "verilog" ++ block = f"{ram}_core" if verilog_periphery else ram ++ periphery_v = out_dir / f"{ram}.periphery.v" + libs = os.environ.get("LIB_FILES", "").split() + if not libs: + raise SystemExit("regfile_ram: generate_ram needs LIB_FILES") @@ -511,7 +536,8 @@ new file mode 100644 + reads + + "".join(f"read_lef {lef}\n" for lef in lefs) + + "generate_ram_netlist " -+ + " ".join(_args(spec_lines, block, shape)) ++ + " ".join(_args(spec_lines, ram, shape)) ++ + (f" -wrapper_verilog {periphery_v}" if verilog_periphery else "") + + f"\nwrite_db {out_dir / f'{block}.odb'}\n" + + "set die [[ord::get_db_block] getDieArea]\n" + + f"set f [open {outline} w]\n" @@ -566,16 +592,23 @@ new file mode 100644 + tcl += _MACRO_TCL.format(out=out_dir, block=block) + views.write_text(tcl) + subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(views)]) -+ ram_ports = _buses((out_dir / f"{block}.ports").read_text().splitlines()) ++ core_ports = _buses((out_dir / f"{block}.ports").read_text().splitlines()) ++ ram_ports = core_ports ++ periphery = "" ++ if verilog_periphery: ++ periphery = periphery_v.read_text() ++ ram_ports = _module_header_ports(periphery, ram) + rtl_ports = _module_ports(out_dir.parent / "memories_inferred.json", module) -+ wrapper = _wrapper(lines, module, block, ram_ports, rtl_ports) ++ wrapper = _wrapper(lines, module, ram, ram_ports, rtl_ports) ++ if periphery: ++ wrapper += "\n" + periphery + if shape == "inline": + wrapper += "\n" + (out_dir / f"{block}.netlist.v").read_text() + else: + # the macro, a blackbox to synthesis + decl = ",\n".join( + f" {d} {'' if w == 1 else f'[{w - 1}:0] '}{n}" -+ for n, (d, w) in ram_ports.items() ++ for n, (d, w) in core_ports.items() + ) + wrapper += f"\n(* blackbox *)\nmodule {block} (\n{decl}\n);\nendmodule\n" + (out_dir / f"{module}.v").write_text(wrapper) diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 962e80e45..27fe49ce9 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -164,7 +164,8 @@ ASAP7 = { # read addresses (patch 0017), on Q and QN flops; and holding words by a # mux per bit instead of a clock gate (patch 0018), and with its periphery # left unplaced (patch 0019); with cells given by role (patch 0020); and a -# word's bits folded into rows (patch 0022). +# word's bits folded into rows (patch 0022); and the periphery as Verilog +# around the core (patch 0023), clock gates and tristates included. [ [ genrule( @@ -190,6 +191,9 @@ read_db $(@D)/{name}.odb write_verilog $(@D)/{name}.v TCL $(location @openroad//:openroad) -exit -no_init -no_splash $(@D)/{name}_v.tcl >> $(@D)/{name}.log 2>&1 || {{ cat $(@D)/{name}.log; exit 1; }} +# -periphery verilog: the wrapper (the periphery as Verilog) around the +# core's netlist +if [ -f $(@D)/{name}_wrap.v ]; then cat $(@D)/{name}_wrap.v >> $(@D)/{name}.v; fi sed -e 's/^module RAM{words}x8 /module RAM8x8_gen /' $(@D)/{name}.v > $(location {name}_gen.v) sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) """.format( @@ -254,5 +258,7 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_cells_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -cells {inv INVx1_ASAP7_75t_R and2 AND2x2_ASAP7_75t_R buffer BUFx2_ASAP7_75t_R aoi22 AOI22x1_ASAP7_75t_R ao22 AO22x2_ASAP7_75t_R or2 OR2x2_ASAP7_75t_R nand2 NAND2x1_ASAP7_75t_R nor2 NOR2x1_ASAP7_75t_R} -name RAM8x8", "tb_ram_2w", 8), ("ram_2w_folds", NANGATE45, "-storage_cell DFF_X1 -mask_size 4 -bit_folds 2 -decoder word", "tb_ram_2w", 8), ("ram_2w_folds_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -mask_size 2 -bit_folds 4 -banks 4 -bank_columns 2 -bank_order interleaved -write_style mux -read_latency 1", "tb_ram_2w", 8), + ("ram_2w_periphery_verilog_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -periphery verilog -pin_layer M4 -wrapper_verilog $(@D)/ram_2w_periphery_verilog_asap7_wrap.v -banks 4 -bank_columns 2 -write_style mux", "tb_ram_2w", 8), + ("ram_2w_periphery_verilog", NANGATE45, "-storage_cell DFF_X1 -periphery verilog -pin_layer metal4 -wrapper_verilog $(@D)/ram_2w_periphery_verilog_wrap.v", "tb_ram_2w", 8), ] ] From c04bb6acd8f320d9ac7807bda8216d9c1ffbc824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 11:16:24 +0200 Subject: [PATCH 25/26] regfile: kept macros and ibex through generate_ram (ORFS 0109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ORFS 0109's translation now covers a register file kept as a macro to the end: its pins placed on its edges by OpenROAD's pin placer on the spec's pin layers (tracks made from those layers' own pitch), and its liberty from write_timing_model, the block's own timing for the parent's STA, with the area the flow costs it by written in. riscv32i's macro arm gets there and stops at the floorplan: 61.5 x 8.9 um with its periphery does not fit a 60.2 um core at 62 %. Every port an `unused` or `reset` line lists is declared, not the first only. test/regfile/cores: regfile_sim_test takes generator = "generate_ram", which builds the spec through ORFS's own regfile_ram.py, the netlist AUTO_MEMORIES_REGFILES inlines. ibex's register file through it matches ibex's RTL under random reads, writes and resets (asynchronous reset to 0, unused inputs, x0); write priority as before; both negative controls fail as they should. regfile_ram.py is exported from the generated flow package for it. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- orfs_source.bzl | 3 + patches/0109-orfs-regfiles-generate-ram.patch | 63 +++++++++++++---- test/regfile/cores/BUILD.bazel | 53 +++++++++++++++ test/regfile/cores/ram_gen.py | 43 ++++++++++++ test/regfile/cores/sim.bzl | 68 ++++++++++++++----- 5 files changed, 200 insertions(+), 30 deletions(-) create mode 100644 test/regfile/cores/ram_gen.py diff --git a/orfs_source.bzl b/orfs_source.bzl index 0f1585f91..32c10d649 100644 --- a/orfs_source.bzl +++ b/orfs_source.bzl @@ -343,6 +343,9 @@ exports_files( exports_files( [ "scripts/flow.tcl", + # the register-file spec's translation to generate_ram (ORFS patch + # 0109), which test/regfile/cores runs on its own + "scripts/memories/regfile_ram.py", "scripts/synth.tcl", "scripts/variables.yaml", ], diff --git a/patches/0109-orfs-regfiles-generate-ram.patch b/patches/0109-orfs-regfiles-generate-ram.patch index 5c9d934f7..800ed98b1 100644 --- a/patches/0109-orfs-regfiles-generate-ram.patch +++ b/patches/0109-orfs-regfiles-generate-ram.patch @@ -58,7 +58,7 @@ diff --git a/flow/scripts/memories/regfile_ram.py b/flow/scripts/memories/regfil new file mode 100644 --- /dev/null +++ b/flow/scripts/memories/regfile_ram.py -@@ -0,0 +1,558 @@ +@@ -0,0 +1,597 @@ +"""AUTO_MEMORIES_REGFILES through OpenROAD's generate_ram. + +A register-file spec (the keys generate_regfile reads) is translated to @@ -72,15 +72,16 @@ new file mode 100644 +- inlined: its netlist follows the wrapper in .v; +- mode netlist: a macro with its periphery unplaced, which + regfile_dissolve.tcl dissolves after macro placement from -+ _ram.v (one instance a line) and _ram.place. ++ _ram.v (one instance a line) and _ram.place; ++- mode macro: a macro kept to the end. + +The flops take the RTL's names where the spec gives them (store_name, +read_reg_name), for equivalence checking: renamed in the database from +generate_ram's own. With `periphery verilog` generate_ram writes the +periphery as a Verilog module, _ram, around the core, -+_ram_core, which is then what is inlined or the macro. A -+register file kept as a macro to the end is left to generate_regfile -+for now; supported() says which. ++_ram_core, which is then what is inlined or the macro. A macro ++kept to the end (mode macro) gets its pins from OpenROAD's pin placer on ++the spec's pin layers and its liberty from write_timing_model. +""" + +from __future__ import annotations @@ -88,6 +89,7 @@ new file mode 100644 +import json +import math +import os ++import re +import subprocess +from pathlib import Path + @@ -143,7 +145,7 @@ new file mode 100644 + which generate_ram_netlist does only with its periphery unplaced.""" + lines = parse(spec) + keys = {line[0] for line in lines} -+ return not (keys & UNSUPPORTED) and shape != "macro" ++ return not (keys & UNSUPPORTED) + + +def _address_bits(words: int) -> int: @@ -439,10 +441,11 @@ new file mode 100644 + return f"{{{width - have}'b0, {name}}}" + + conns["clk"] = port(_one(lines, "clock", "clock"), "input", 1) -+ for values in _values(lines, "reset"): -+ port(values[0], "input", 1) -+ for values in _values(lines, "unused"): -+ port(values[0], "input", 1) ++ # ports the RTL has and the array ignores, any number a line ++ for key in ("reset", "unused"): ++ for values in _values(lines, key): ++ for name in values: ++ port(name, "input", 1) + for values in _values(lines, "async_reset"): + name = port(values[0], "input", 1) + low = values[1] == "low" if len(values) > 1 else True @@ -541,13 +544,13 @@ new file mode 100644 + + f"\nwrite_db {out_dir / f'{block}.odb'}\n" + + "set die [[ord::get_db_block] getDieArea]\n" + + f"set f [open {outline} w]\n" -+ + "puts $f \"[$die dx] [$die dy]\"\n" ++ + "puts $f \"[$die dx] [$die dy] [[ord::get_db_tech] getDbUnitsPerMicron]\"\n" + + "close $f\n" + ) + subprocess.check_call( + [openroad, "-exit", "-no_init", "-no_splash", str(gen)] + ) -+ width, height = outline.read_text().split() ++ width, height, _ = outline.read_text().split() + return float(width), float(height) + + width, height = build(lines) @@ -589,9 +592,45 @@ new file mode 100644 + if shape == "inline": + tcl += f"write_verilog {out_dir / f'{block}.netlist.v'}\n" + else: ++ if shape == "macro": ++ # a macro kept to the end: its pins on its edges, by the pin ++ # placer ++ h = _one(lines, "pin_layer", _one(lines, "pin_layer_h", "M4")) ++ v = _one(lines, "pin_layer_v", "M5") ++ # tracks on the two pin layers, from their own pitch ++ for layer in (h, v): ++ tcl += ( ++ f"set l [[ord::get_db_tech] findLayer {layer}]\n" ++ "set u [[ord::get_db_tech] getDbUnitsPerMicron]\n" ++ "set p [expr {double([$l getPitch]) / $u}]\n" ++ "set o [expr {double([$l getOffset]) / $u}]\n" ++ f"make_tracks {layer} -x_offset $o -x_pitch $p" ++ " -y_offset $o -y_pitch $p\n" ++ ) ++ tcl += f"place_pins -hor_layers {h} -ver_layers {v}\n" + tcl += _MACRO_TCL.format(out=out_dir, block=block) ++ if shape == "macro": ++ # and its timing, the block's own, for the parent's STA ++ clock = "clk" ++ tcl += ( ++ f"create_clock -name {clock} -period 1 [get_ports {clock}]\n" ++ "estimate_parasitics -placement\n" ++ f"write_timing_model {out_dir / f'{block}.lib'}\n" ++ ) + views.write_text(tcl) + subprocess.check_call([openroad, "-exit", "-no_init", "-no_splash", str(views)]) ++ if shape == "macro": ++ # write_timing_model states no area; the flow costs a macro by it ++ width, height, dbu = (float(v) for v in outline.read_text().split()) ++ lib = out_dir / f"{block}.lib" ++ text = lib.read_text() ++ text = re.sub( ++ r"(cell\s*\(\s*\\?\"?" + re.escape(block) + r"\"?\s*\)\s*\{)", ++ lambda m: m.group(1) + f"\n area : {width * height / dbu / dbu:.4f};", ++ text, ++ count=1, ++ ) ++ lib.write_text(text) + core_ports = _buses((out_dir / f"{block}.ports").read_text().splitlines()) + ram_ports = core_ports + periphery = "" diff --git a/test/regfile/cores/BUILD.bazel b/test/regfile/cores/BUILD.bazel index b26c727d7..28c7b26c9 100644 --- a/test/regfile/cores/BUILD.bazel +++ b/test/regfile/cores/BUILD.bazel @@ -20,6 +20,12 @@ py_binary( main = "gen_tb.py", ) +py_binary( + name = "ram_gen", + srcs = ["ram_gen.py"], + main = "ram_gen.py", +) + stdcell_verilog( name = "asap7_stdcell", lefs = ["@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef"], @@ -74,3 +80,50 @@ regfile_sim_test( rtl_module = "rf_wp", spec = ":rf_wp.regfile", ) + +# The same four through generate_ram (OpenROAD patches 0011 to 0023), by +# ORFS's own translation of the spec (regfile_ram.py, patch 0109): the +# wrapper in the RTL module's place, the reset's polarity adapted there, +# the unused inputs, the write priority; the negative controls show the +# harness sees generate_ram's netlist too. +[ + regfile_sim_test( + name = name, + expect_mismatch = expect_mismatch, + generator = "generate_ram", + module = module, + rtl = rtl, + rtl_module = module, + spec = spec, + ) + for name, module, spec, rtl, expect_mismatch in [ + ( + "ibex_ram_sim_test", + "ibex_register_file_ff", + ":ibex_register_file_ff.regfile", + ["@orfs//flow/designs/src/ibex_sv:ibex_register_file_ff.sv"], + False, + ), + ( + "ibex_no_reset_ram_sim_test", + "ibex_register_file_ff", + ":ibex_no_reset.regfile", + ["@orfs//flow/designs/src/ibex_sv:ibex_register_file_ff.sv"], + True, + ), + ( + "write_last_ram_sim_test", + "rf_wp", + ":rf_wp.regfile", + [":write_last.v"], + False, + ), + ( + "write_first_ram_sim_test", + "rf_wp", + ":rf_wp.regfile", + [":write_first.v"], + True, + ), + ] +] diff --git a/test/regfile/cores/ram_gen.py b/test/regfile/cores/ram_gen.py new file mode 100644 index 000000000..5aa469755 --- /dev/null +++ b/test/regfile/cores/ram_gen.py @@ -0,0 +1,43 @@ +"""A register-file spec through ORFS's regfile_ram.py and generate_ram. + +The netlist AUTO_MEMORIES_REGFILES inlines for the spec (the wrapper in +the RTL module's place around generate_ram's RAM), its module renamed +_gen, for regfile_sim_test to simulate beside the reference. +""" + +import argparse +import importlib.util +import os +import sys +import tempfile +from pathlib import Path + + +def main() -> int: + p = argparse.ArgumentParser(description=__doc__) + p.add_argument("--regfile-ram", required=True, type=Path) + p.add_argument("--spec", required=True, type=Path) + p.add_argument("--module", required=True) + p.add_argument("--openroad", required=True) + p.add_argument("--lef", action="append", default=[], type=Path) + p.add_argument("--lib", action="append", default=[]) + p.add_argument("--out", required=True, type=Path) + args = p.parse_args() + spec = importlib.util.spec_from_file_location("regfile_ram", args.regfile_ram) + regfile_ram = importlib.util.module_from_spec(spec) + spec.loader.exec_module(regfile_ram) + os.environ["LIB_FILES"] = " ".join(args.lib) + with tempfile.TemporaryDirectory(dir=args.out.parent) as work: + out_dir = Path(work) / "memories" + out_dir.mkdir() + regfile_ram.generate( + args.spec, args.module, "inline", args.openroad, args.lef, out_dir + ) + text = (out_dir / f"{args.module}.v").read_text() + text = text.replace(f"module {args.module} (", f"module {args.module}_gen (", 1) + args.out.write_text(text) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/test/regfile/cores/sim.bzl b/test/regfile/cores/sim.bzl index 003b59fc6..87a74d150 100644 --- a/test/regfile/cores/sim.bzl +++ b/test/regfile/cores/sim.bzl @@ -1,7 +1,8 @@ """regfile_sim_test: a spec's generated netlist simulated beside its reference. -generate_regfile builds the spec into a structural netlist of asap7 -cells; gen_tb.py writes a testbench that drives it and the reference +generate_regfile, or generate_ram through ORFS's translation of the spec +(regfile_ram.py, the netlist AUTO_MEMORIES_REGFILES inlines), builds the +spec into a structural netlist of asap7 cells; gen_tb.py writes a testbench that drives it and the reference (the RTL module the spec replaces, or a behavioural memory built from the spec when there is none) with the same random reads, writes and resets, and the test fails on the first differing read. @@ -13,6 +14,14 @@ load("@rules_verilog//verilog:defs.bzl", "verilog_library") _TECH_LEF = "@orfs//flow:platforms/asap7/lef/asap7_tech_1x_201209.lef" _CELL_LEF = "@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef" +_LIBS = [ + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_AO_RVT_TT_nldm_211120.lib.gz", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_INVBUF_RVT_TT_nldm_220122.lib.gz", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_OA_RVT_TT_nldm_211120.lib.gz", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_SEQ_RVT_TT_nldm_220123.lib", + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_SIMPLE_RVT_TT_nldm_211120.lib.gz", +] +_REGFILE_RAM = "@orfs//flow:scripts/memories/regfile_ram.py" def regfile_sim_test( name, @@ -22,7 +31,8 @@ def regfile_sim_test( rtl_module = None, ties = {}, expect_mismatch = False, - stdcells = ":asap7_stdcell"): + stdcells = ":asap7_stdcell", + generator = "generate_regfile"): """Simulates generate_regfile's netlist for `spec` against a reference. Args: @@ -36,15 +46,37 @@ def regfile_sim_test( expect_mismatch: a negative control, a spec known to be wrong: the test passes only if some read differs. stdcells: the stdcell_verilog target. + generator: generate_regfile, or generate_ram through regfile_ram.py. """ + if generator == "generate_ram": + native.genrule( + name = name + "_gen_v", + srcs = [spec, _TECH_LEF, _CELL_LEF, _REGFILE_RAM] + _LIBS, + outs = [name + "_gen.v"], + cmd = " ".join([ + "grep -v '^[[:space:]]*memory[[:space:]]' $(location %s) > $(@D)/%s.regfile &&" % (spec, name), + "$(execpath :ram_gen)", + "--regfile-ram $(location %s)" % _REGFILE_RAM, + "--spec $(@D)/%s.regfile" % name, + "--module " + module, + "--openroad $(location @openroad//:openroad)", + "--lef $(location %s) --lef $(location %s)" % (_TECH_LEF, _CELL_LEF), + ] + ["--lib $(location %s)" % lib for lib in _LIBS] + [ + "--out $@", + ]), + tools = ["@openroad", ":ram_gen"], + ) check = "" - if rtl_module: + if generator == "generate_ram": + pass + elif rtl_module: check = "-check_ports " + " ".join(["$(location %s)" % r for r in rtl]) - native.genrule( - name = name + "_gen_v", - srcs = [spec, _TECH_LEF, _CELL_LEF] + rtl, - outs = [name + "_gen.v"], - cmd = """ + if generator != "generate_ram": + native.genrule( + name = name + "_gen_v", + srcs = [spec, _TECH_LEF, _CELL_LEF] + rtl, + outs = [name + "_gen.v"], + cmd = """ grep -v '^[[:space:]]*memory[[:space:]]' $(location {spec}) > $(@D)/{name}.regfile cat > $(@D)/{name}.tcl < $( sed 's/^module {module}(/module {module}_gen(/' $(@D)/{name}.raw.v > $@ grep -q '^module {module}_gen(' $@ || {{ echo 'no module {module} in the netlist'; exit 1; }} """.format( - name = name, - tech = _TECH_LEF, - cell = _CELL_LEF, - spec = spec, - check = check, - module = module, - ), - tools = ["@openroad"], - ) + name = name, + tech = _TECH_LEF, + cell = _CELL_LEF, + spec = spec, + check = check, + module = module, + ), + tools = ["@openroad"], + ) tie_args = " ".join(["--tie %s=%s" % (k, v) for k, v in ties.items()]) native.genrule( name = name + "_tb", From abee1b8de216aa72dde7adba55875fed6a6bca78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 13 Oct 2026 15:34:47 +0200 Subject: [PATCH 26/26] regfile: drop patch 0010, everything on generate_ram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing uses generate_regfile any more: the equivalence checks (test/structured_gen_lec), structured_gen's golden test, the planner, the scaffolds and the planned parent's probes build or find generate_ram's RAM, through ORFS's regfile_ram.py, in the wrapper that takes the module's place. What the XiangShan register files needed beyond 0011 to 0023, each an option on generate_ram, default unchanged: - 0024 -write_priority or: colliding writes OR'd, as firtool's register files describe them (the mux-write equivalence checks failed without). - 0022, amended: -bit_folds with a short last fold (211 bits in 4, 954 in 8). - 0025 -service_columns: generate_regfile's tap_columns and service_sites, which regfile_ram.py had ignored. - 0026 -bank_column_layout contiguous: a row's words side by side, not interleaved bit by bit; RobEntryFile's parent found 6,483 slew violations on selects running the row, 608 with it, and legalizes. regfile_ram.py: write_priority, bank_column_layout (contiguous by default where a row holds more than one word, as generate_regfile's tile per word), the service keys, a power grid and VDD/VSS pins for a macro kept to the end, and a fold where a word's bits would span more than 150 um (RenameBufferFile, a word a row 258 um wide, did not legalize). The scaffolds' outlines are generate_ram's, and their ring holds the periphery generate_ram leaves to the parent. ideas/tile-generator.md: a tile generator beside generate_ram, for later in the campaign. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Øyvind Harboe --- MODULE.bazel | 22 +- config_mk_parser.py | 2 +- ideas/tile-generator.md | 51 + orfs_source.bzl | 5 +- .../0010-openroad-ram-generate-regfile.patch | 4187 ----------------- ...11-openroad-ram-multiple-write-ports.patch | 18 +- patches/0012-openroad-ram-and-or-read.patch | 49 +- patches/0013-openroad-ram-zero-word.patch | 22 +- patches/0014-openroad-ram-reset.patch | 16 +- patches/0015-openroad-ram-banks.patch | 16 +- .../0016-openroad-ram-banked-read-ports.patch | 16 +- patches/0017-openroad-ram-read-latency.patch | 16 +- patches/0018-openroad-ram-write-mux.patch | 16 +- ...0019-openroad-ram-periphery-unplaced.patch | 16 +- patches/0020-openroad-ram-cells-name.patch | 12 +- patches/0021-openroad-ram-word-decoder.patch | 12 +- patches/0022-openroad-ram-bit-folds.patch | 172 +- .../0023-openroad-ram-periphery-verilog.patch | 28 +- .../0024-openroad-ram-write-priority-or.patch | 1639 +++++++ .../0025-openroad-ram-service-columns.patch | 1013 ++++ ...0026-openroad-ram-bank-column-layout.patch | 1035 ++++ patches/0109-orfs-regfiles-generate-ram.patch | 121 +- private/rules.bzl | 2 +- private/stages.bzl | 2 +- .../designs/asap7/xiangshan/BUILD | 2 +- .../asap7/xiangshan/plan/place_macros.tcl | 11 +- test/planned_parent/leftover_macros.tcl | 34 +- test/planned_parent/plan/place_macros.tcl | 11 +- test/regfile/BUILD.bazel | 14 +- test/regfile/RegFile.regfile | 2 +- test/regfile/cores/BUILD.bazel | 77 +- test/regfile/cores/gen_tb.py | 5 +- .../cores/ibex_register_file_ff.regfile | 2 +- test/regfile/cores/ram_gen.py | 18 +- test/regfile/cores/sim.bzl | 77 +- test/regfile/regfile_top.v | 2 +- test/regfile/riscv32i/BUILD.bazel | 11 +- test/regfile/sim/BUILD.bazel | 105 +- test/regfile/sim/regfile.regfile | 17 - test/regfile/sim/tb_main.cc | 60 - test/regfile/sim/tb_top.v | 23 - test/structured_gen_lec/BUILD | 18 +- test/structured_gen_lec/regfile_lec.bzl | 52 +- test/structured_netlist/BUILD.bazel | 21 +- test/structured_netlist/scaffold.bzl | 22 +- test/structured_netlist/scaffold_gen.py | 11 +- tools/macro_select/plan_floorplan.py | 11 +- tools/structured_gen/BUILD.bazel | 28 +- tools/structured_gen/golden_test.sh | 49 +- tools/structured_gen/test/BUILD.bazel | 11 +- 50 files changed, 4432 insertions(+), 4750 deletions(-) create mode 100644 ideas/tile-generator.md delete mode 100644 patches/0010-openroad-ram-generate-regfile.patch create mode 100644 patches/0024-openroad-ram-write-priority-or.patch create mode 100644 patches/0025-openroad-ram-service-columns.patch create mode 100644 patches/0026-openroad-ram-bank-column-layout.patch delete mode 100644 test/regfile/sim/regfile.regfile delete mode 100644 test/regfile/sim/tb_main.cc delete mode 100644 test/regfile/sim/tb_top.v diff --git a/MODULE.bazel b/MODULE.bazel index ad1b4ed64..bfdbc8348 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -121,16 +121,11 @@ archive_override( # pull request carries a gtest. Retires at a bump onto an OpenROAD # that has it. "//patches:0004-openroad-dpl-window-supply.patch", - # 0010: generate_regfile in the ram module, a multi-port register - # file as placed standard cells, which AUTO_MEMORIES_REGFILES - # (ORFS patch 0089) runs. The net diff of upstream - # The-OpenROAD-Project/OpenROAD#11669; retires at a bump onto an - # OpenROAD that has it. - "//patches:0010-openroad-ram-generate-regfile.patch", + # 0011 to 0026: OpenROAD #11669's register-file generator carried + # onto generate_ram, as options on it, one patch per pull request + # to come; not upstreamed. # 0011: generate_ram with more than one write port, each with its # own decoder and data, the last port winning a word both write. - # The first generate_regfile feature carried onto generate_ram - # (OpenROAD #11669); not upstreamed. "//patches:0011-openroad-ram-multiple-write-ports.patch", # 0012: generate_ram reads through AND-OR trees where the library # has no tristate cell (asap7), or when asked; a QN-only storage @@ -173,6 +168,17 @@ archive_override( # its own and its periphery a Verilog wrapper. On 0022 (OpenROAD # #11669); not upstreamed. "//patches:0023-openroad-ram-periphery-verilog.patch", + # 0024: generate_ram -write_priority or, ports writing one word in + # a cycle write the OR of their data. On 0023 (OpenROAD #11669); + # not upstreamed. + "//patches:0024-openroad-ram-write-priority-or.patch", + # 0025: generate_ram -service_columns, empty columns in the array + # for a parent's buffers. On 0024 (OpenROAD #11669); not upstreamed. + "//patches:0025-openroad-ram-service-columns.patch", + # 0026: generate_ram -bank_column_layout contiguous, a word's bits + # side by side in its row. On 0025 (OpenROAD #11669); not + # upstreamed. + "//patches:0026-openroad-ram-bank-column-layout.patch", ], strip_prefix = "OpenROAD-a3bf6124782f205ba5fa9e2e402dae8b665fc4fc", urls = ["https://github.com/The-OpenROAD-Project/OpenROAD/archive/a3bf6124782f205ba5fa9e2e402dae8b665fc4fc.tar.gz"], diff --git a/config_mk_parser.py b/config_mk_parser.py index fa887b511..5d26a81a2 100644 --- a/config_mk_parser.py +++ b/config_mk_parser.py @@ -65,7 +65,7 @@ # before synthesis; run during canonicalization, so staged. "SYNTH_VERILOG_SURGERY", # AUTO_MEMORIES_REGFILES: register-file spec files gen_memories.py - # hands to OpenROAD's generate_regfile during canonicalization; + # translates to OpenROAD's generate_ram during canonicalization; # staged like the .memories files above. "AUTO_MEMORIES_REGFILES", } diff --git a/ideas/tile-generator.md b/ideas/tile-generator.md new file mode 100644 index 000000000..a57e0e6fd --- /dev/null +++ b/ideas/tile-generator.md @@ -0,0 +1,51 @@ +# A tile generator beside generate_ram + +An idea for later in the register-file campaign, not started. The user +injects a repeating netlist, a tile, and a generic engine lays out the +array of it: the tile's cells placed once by a solver (OR-tools CP-SAT), +the array tiled by construction, the periphery built by hooks. It would +sit *beside* generate_ram, not replace it. generate_ram covers storage +with one word per row, decoders and read trees; the engine would cover +the repeating structures generate_ram cannot express: + +- CAMs: a compare cell per bit, a match line per row reduced across it; +- systolic and multiply-accumulate arrays: a 2-D tile wired to its + neighbours, no decoder; +- FIFOs and shift or delay lines: a pointer ring as the periphery; +- datapath bit-slices (adders, shifters, muxes): a bit per row, the + carry chain a net between neighbouring tiles. + +## What the user injects + +1. The tile netlist, of liberty cells, each port declared row-shared, + column-shared, wired to a neighbour (N, E, S, W) or periphery. +2. Tiling rules: the tile's height in rows, its column pitch, mirroring + per row and column. +3. Periphery hooks: a generator per row or column edge (decoder, driver, + reduction tree, pointer), each matched to the tile's pitch. +4. Optionally, hints for the tile's solve: fixed cells, pin sides. + +Exact solvers handle tens to a few hundred objects, so CP-SAT fits the +tile and the small choices around it (fold, aspect ratio, pin sides), +not the array. + +## Prior art + +A literature search (2026-10-13) found the pieces but not the +combination, and no published placement work that uses CP-SAT. + +- Injected cells, tiled: OpenRAM (https://github.com/VLSIDA/OpenRAM), + its bitcell and periphery modules overridable per technology; SRAM22 + on Substrate, typed composable generators (Berkeley EECS-2023-137). + Both are custom-layout SRAMs only. +- Standard-cell RAMs of fixed cells: DFFRAM, whose density came from a + placer that knew its structure (https://github.com/AUCOHL/DFFRAM); + OpenROAD's ram module, arXiv 2607.12244 (Louie, Nguyen, Liberty, + Rovinski). +- Bit-slice alignment in a general placer: Ward et al., SAPT, IEEE + TCAD 32(2), 2013; regularity extraction, Chowdhary et al., ICCAD 1998. +- Exact solvers for small layouts: SMTCell (UCSD), BonnCell (Bonn); ILP + detailed placement under array constraints in ALIGN, arXiv 2008.10682. + +Read first: arXiv 2607.12244, OpenRAM's override design with +EECS-2023-137, then SAPT and ALIGN. diff --git a/orfs_source.bzl b/orfs_source.bzl index 32c10d649..adad2e51a 100644 --- a/orfs_source.bzl +++ b/orfs_source.bzl @@ -124,7 +124,7 @@ ORFS_PATCHES = [ # //:bump onto an ORFS that carries it. Label("//patches:0094-orfs-synth-verilog-surgery.patch"), # 0089: AUTO_MEMORIES_REGFILES: register files listed by spec are - # built by OpenROAD's generate_regfile (OpenROAD patch 0010) as + # built by OpenROAD's generate_ram (OpenROAD patches 0011 to 0023) as # macros of placed standard cells; in `mode netlist` each dissolves # into its cells at the end of macro placement, its core FIRM where # the macro was placed, its address decode left to placement. @@ -165,8 +165,7 @@ ORFS_PATCHES = [ # upstreamed. Label("//patches:0108-orfs-regfile-periphery-verilog.patch"), # 0109: register files through generate_ram (OpenROAD patches 0011 to - # 0020) where it builds the spec, a wrapper in the RTL module's place; - # the rest stay with generate_regfile. On 0089, 0091 and 0108; retires + # 0023), a wrapper in the RTL module's place; every spec. On 0089, 0091 and 0108; retires # with 0089. Not upstreamed. Label("//patches:0109-orfs-regfiles-generate-ram.patch"), ] diff --git a/patches/0010-openroad-ram-generate-regfile.patch b/patches/0010-openroad-ram-generate-regfile.patch deleted file mode 100644 index abdf7254b..000000000 --- a/patches/0010-openroad-ram-generate-regfile.patch +++ /dev/null @@ -1,4187 +0,0 @@ -From 691d8e15184d6d7baf40944536dc5980f8b9a685 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=98yvind=20Harboe?= -Date: Fri, 9 Oct 2026 10:00:00 +0200 -Subject: [PATCH] ram: generate_regfile, a multi-port register file as placed - standard cells -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The net diff of The-OpenROAD-Project/OpenROAD#11669 at its head -691d8e15, all eight commits as one patch: generate_regfile in src/ram, -async_reset, SystemVerilog port headers and `unused `, -write_priority, Port fields named in the spec reader, and RAM-0052 for -what mode netlist leaves unplaced. - -generate_regfile builds a register file with many read and write ports -over few words as an array of placed standard cells, from a spec that -names the module, its words and bits, its ports by the RTL's own port -names, and the cells to use. It writes structural Verilog, DEF, an -abstract LEF and a timing model. ORFS's AUTO_MEMORIES_REGFILES (ORFS -patch 0089, The-OpenROAD-Project/OpenROAD-flow-scripts#4651) runs it -during canonicalization. - -Upstream as The-OpenROAD-Project/OpenROAD#11669; retires at a bump onto -an OpenROAD that has it. - -diff --git a/src/ram/BUILD b/src/ram/BUILD -index 2cb8a34b5e9..fa9f8c8ce2e 100644 ---- a/src/ram/BUILD -+++ b/src/ram/BUILD -@@ -18,6 +18,11 @@ cc_library( - "src/MakeRam.cpp", - "src/layout.cpp", - "src/ram.cpp", -+ "src/regfile.cpp", -+ "src/regfile.h", -+ "src/regfile_cmd.cpp", -+ "src/views.cpp", -+ "src/views.h", - ":swig", - ":tcl", - ], -@@ -25,6 +30,7 @@ cc_library( - "include/ram/MakeRam.h", - "include/ram/layout.h", - "include/ram/ram.h", -+ "include/ram/regfile.h", - ], - includes = [ - "include", -@@ -36,6 +42,8 @@ cc_library( - "//src/drt", - "//src/grt", - "//src/odb/src/db", -+ "//src/odb/src/defout", -+ "//src/odb/src/lefout", - "//src/pdn", - "//src/ppl", - "//src/sta:opensta_lib", -diff --git a/src/ram/CMakeLists.txt b/src/ram/CMakeLists.txt -index d0008e8664d..81aaa4ab9a4 100644 ---- a/src/ram/CMakeLists.txt -+++ b/src/ram/CMakeLists.txt -@@ -15,6 +15,9 @@ target_sources(ram - src/ram.cpp - src/layout.cpp - src/MakeRam.cpp -+ src/regfile.cpp -+ src/regfile_cmd.cpp -+ src/views.cpp - ) - - target_include_directories(ram -diff --git a/src/ram/README.md b/src/ram/README.md -index 94c5df30369..034eb02a14c 100644 ---- a/src/ram/README.md -+++ b/src/ram/README.md -@@ -80,9 +80,71 @@ generate_ram [-mask_size bits] - | `-use_latch` | If set to `1`, uses a two-phase latch-based design instead of flip-flops for the storage elements. Functionally equivalent to flip-flop design with smaller storage cell area. Default: `0`. | - | `-write_behavioral_verilog` | Write a behavioral Verilog model of the RAM array to the specified file. | - -+### Register File Generation -+ -+The `generate_regfile` command builds a register file, many read and -+write ports over few words, as an array of placed standard cells: word -+rows by bit columns, each tile a flop, its write select and an AND per -+read port, the read word lines decoded in a header column and the read -+bit lines as OR trees in a footer row. Every cell is placed by -+construction. The block is built into the current database, whose -+libraries must hold the cells the spec names. -+ -+```tcl -+generate_regfile -spec file -+ [-check_ports verilog_file] -+ [-verilog file] -+ [-def file] -+ [-lef file] -+ [-liberty file] -+``` -+ -+#### Options -+ -+| Switch Name | Description | -+| ---------------------- | -------------------------------------- | -+| `-spec` | The spec file, below. | -+| `-check_ports` | A Verilog file declaring the spec's module. The command stops if the module's ports are not the ports the spec names, at the widths the spec implies. It reads ANSI headers, a SystemVerilog `#(...)` parameter list and widths written in its parameters' defaults, packed dimensions multiplied; a port declaration it cannot read stops it too. | -+| `-verilog` | Write the cells as structural Verilog. | -+| `-def` | Write the placed block as DEF. | -+| `-lef` | Write an abstract LEF of the block. | -+| `-liberty` | Write a timing model; a `_pre_layout.lib` beside it has ideal clocks. | -+ -+#### Spec -+ -+One key per line, `#` comments: -+ -+| Key | Description | -+| ---------------------- | -------------------------------------- | -+| `module name` | The module and block name. | -+| `mode macro\|netlist` | `macro` (default): the block is a macro to its parent; every cell is placed, the address inverters placed but movable so the macro's own repair can size them. `netlist`: the block is placed as a macro and then dissolves into its parent's cells: the core (storage flops and read bitlines) is fixed where it lies, and the periphery (address inverters, decode, hold) is left unplaced, RAM-0052 says how much, for the parent's placer and resizer, which alone know the drivers and loads outside the array; the abstract is the core's bounding box, its pins where their connections land in the array. Which shape is better, and whether the periphery should be unplaced or placed but movable, is still being measured. | -+| `words n`, `bits n` | Depth and width. | -+| `clock port` | The clock port. | -+| `reset port` | A reset port the RTL has and the array ignores. | -+| `write_priority or\|last` | Two ports writing one word in one cycle: `or` (the default) ORs their data, for an RTL that never does it; `last`, the later write port in the spec wins, as an RTL's later assignment does. | -+| `unused port...` | One-bit inputs the RTL module has and the array ignores (ibex's `test_en_i`), so the block keeps the module's ports. | -+| `async_reset port low\|high` | The reset clears every stored word to zero asynchronously, active low or high; the storage flops are `cell flop_r` with their set tied off by `cell tie_hi`, one tie (and for an active-high reset one inverter) per word. Read-address registers are not reset. One of `reset` or `async_reset`. | -+| `read addr data` | A read port, by the module's port names. Repeat per port. | -+| `read_banked addr0 data0 addr1 data1 ...` | A read port with an address and a data port per bank. | -+| `write addr data [en]` | A write port. Repeat per port. | -+| `cell role master` | The cells: `flop`, `and2`, `or2`, `ao22`, `inv`, `tap`; with `async_reset` also `flop_r` (pins D, CLK, RESETN, SETN, QN by default) and `tie_hi` (pin H). | -+| `pins role pin...` | The pin names of a cell role (`flop`, `flop_r`, `tie_hi`, `and2`, `or2`, `ao22`, `inv`), for a library whose names differ from the defaults. | -+| `flop_output Q\|QN` | Whether the flop's output is inverted. | -+| `pin_layer layer`, `pin_layer_v layer` | The layers of the pins on the left and right edges, and on the top and bottom. | -+| `pin_track offset pitch` | The track grid the pins are centred on, in microns. | -+| `banks n`, `bank_columns n`, `bank_order contiguous\|interleaved` | Word columns side by side, how many of them stand in a row, and how words fall into them. | -+| `bit_folds n` | The word split into `n` bit bands stacked one above the other. | -+| `read_latency 0\|1` | `1` registers each read address on the clock first. | -+| `zero_word n` | A word with no storage that reads 0 and drops writes (RISC-V x0). | -+| `periphery generator\|verilog` | Who builds the periphery (address inverters, decode, write muxes, hold): `generator` (the default), as cells placed with the array or, in `mode netlist`, left to the parent; `verilog`, as assigns of those cells' functions in the netlist, for synthesis to map with the parent's logic, the clock gates kept as cells. Which is better depends on how the array is integrated. With `mode netlist` the block is the core alone, `_core`, its ports the nets it shares with the periphery: `-lef`, `-liberty` and `-def` describe it, `-verilog` writes the wrapper module, the periphery around an instance of the core declared a blackbox, and `_core.v` beside it the core's netlist. | -+| `tap_columns n`, `service_sites n` | A tap column every `n` bit columns, and free sites beside each for the clock tree: 40 in a macro, none in `mode netlist`, whose clock tree is the parent's. | -+| `store_name pattern`, `read_reg_name pattern` | Instance names of the flops, from `{word}`, `{bit}`, `{port}` and `{bank}`. | -+| `lib knob value` | The timing model's parameters: `gate_delay_ps`, `wire_factor`, `input_load_ff`, `clock_load_ff`, `leakage_nw_per_cell`, `output_max_cap_ff`, `hold_ps`. | -+ - ## Example scripts - --See [test/make_8x8_sky130.tcl](test/make_8x8_sky130.tcl). -+See [test/make_8x8_sky130.tcl](test/make_8x8_sky130.tcl) and -+[test/generate_regfile_asap7.tcl](test/generate_regfile_asap7.tcl). - - ## Regression tests - -diff --git a/src/ram/include/ram/regfile.h b/src/ram/include/ram/regfile.h -new file mode 100644 -index 00000000000..663887e0ec4 ---- /dev/null -+++ b/src/ram/include/ram/regfile.h -@@ -0,0 +1,33 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+// Copyright (c) 2026, The OpenROAD Authors -+ -+#pragma once -+ -+#include -+ -+namespace odb { -+class dbDatabase; -+} -+ -+namespace utl { -+class Logger; -+} -+ -+namespace ram { -+ -+// A multi-port register file as placed standard cells: word rows by bit -+// columns, every cell of its core placed by construction (see -+// src/regfile.h). Reads the spec file, builds the block into `db`, whose -+// libraries must hold the spec's cells, and writes each view whose path -+// is not empty. `check_ports` names a Verilog file whose module the spec -+// must match port for port before anything is built. -+void generateRegfile(odb::dbDatabase* db, -+ utl::Logger* logger, -+ const std::string& spec_path, -+ const std::string& verilog_path, -+ const std::string& def_path, -+ const std::string& lef_path, -+ const std::string& liberty_path, -+ const std::string& check_ports); -+ -+} // namespace ram -diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 8b225fcc890..c4584484fa3 100644 ---- a/src/ram/src/ram.i -+++ b/src/ram/src/ram.i -@@ -8,6 +8,7 @@ - - #include "ord/OpenRoad.hh" - #include "ram/ram.h" -+#include "ram/regfile.h" - #include "utl/Logger.h" - - namespace ord { -@@ -96,6 +97,17 @@ generate_ram_netlist_cmd(int mask_size, - tapcell, max_tap_dist); - } - -+void generate_regfile_cmd(const char* spec_path, -+ const char* verilog_path, -+ const char* def_path, -+ const char* lef_path, -+ const char* liberty_path, -+ const char* check_ports) -+{ -+ generateRegfile(ord::getDb(), ord::getLogger(), spec_path, verilog_path, -+ def_path, lef_path, liberty_path, check_ports); -+} -+ - void ram_pdngen(const char* power_net_name, const char* ground_net_name, - const char* route_name, int route_width, - const char* ver_name, int ver_width, int ver_pitch, -diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 4e58c501636..505b551342a 100644 ---- a/src/ram/src/ram.tcl -+++ b/src/ram/src/ram.tcl -@@ -298,3 +298,28 @@ proc generate_ram { args } { - - ram::ram_routing - } -+ -+sta::define_cmd_args "generate_regfile" {-spec file -+ [-verilog file] -+ [-def file] -+ [-lef file] -+ [-liberty file] -+ [-check_ports verilog_file]} -+ -+# A multi-port register file as placed standard cells, from a spec file -+# (src/regfile.h): the block is built into the current database, whose -+# libraries must hold the spec's cells, and each view asked for is written. -+proc generate_regfile { args } { -+ sta::parse_key_args "generate_regfile" args \ -+ keys { -spec -verilog -def -lef -liberty -check_ports } flags {} -+ sta::check_argc_eq0 "generate_regfile" $args -+ if { ![info exists keys(-spec)] } { -+ utl::error RAM 51 "generate_regfile needs -spec." -+ } -+ set views {} -+ foreach k { -verilog -def -lef -liberty -check_ports } { -+ lappend views [expr { [info exists keys($k)] ? $keys($k) : "" }] -+ } -+ ram::generate_regfile_cmd $keys(-spec) {*}$views -+ ord::design_created -+} -diff --git a/src/ram/src/regfile.cpp b/src/ram/src/regfile.cpp -new file mode 100644 -index 00000000000..fb4b113bda1 ---- /dev/null -+++ b/src/ram/src/regfile.cpp -@@ -0,0 +1,2054 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+// Copyright (c) 2026, The OpenROAD Authors -+ -+// generate_regfile: a multi-port register file as a placed standard-cell -+// macro, built directly in odb. See regfile.h and README.md. -+#include "regfile.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "odb/db.h" -+#include "odb/dbTypes.h" -+#include "odb/geom.h" -+#include "utl/Logger.h" -+ -+namespace ram::regfile { -+ -+namespace { -+ -+using odb::dbBlock; -+using odb::dbBTerm; -+using odb::dbInst; -+using odb::dbMaster; -+using odb::dbNet; -+ -+std::string Bit(const std::string& bus, int i) -+{ -+ return bus + "[" + std::to_string(i) + "]"; -+} -+ -+int AddrBits(int words) -+{ -+ int a = 0; -+ while ((1 << a) < words) { -+ ++a; -+ } -+ return std::max(a, 1); -+} -+ -+[[noreturn]] void Refuse(const std::string& what) -+{ -+ throw std::runtime_error(what); -+} -+ -+// `pattern` with each `{key}` replaced by its value. -+std::string Fmt(std::string pattern, -+ const std::vector>& values) -+{ -+ for (const auto& [key, value] : values) { -+ const std::string k = "{" + key + "}"; -+ for (size_t at = pattern.find(k); at != std::string::npos; -+ at = pattern.find(k, at)) { -+ pattern.replace(at, k.size(), std::to_string(value)); -+ } -+ } -+ return pattern; -+} -+ -+// The pins of each cell kind, asap7's names by default; a spec may -+// override them with `pins ...` in the same order. -+struct Pins -+{ -+ std::vector flop = {"D", "CLK", "QN"}; // data, clock, out -+ // data, clock, reset, set (both active low), out -+ std::vector flop_r = {"D", "CLK", "RESETN", "SETN", "QN"}; -+ std::vector tie_hi = {"H"}; -+ std::vector and2 = {"A", "B", "Y"}; -+ std::vector or2 = {"A", "B", "Y"}; -+ std::vector ao22 = {"A1", "A2", "B1", "B2", "Y"}; -+ std::vector aoi22 = {"A1", "A2", "B1", "B2", "Y"}; -+ std::vector nand2 = {"A", "B", "Y"}; -+ std::vector nor2 = {"A", "B", "Y"}; -+ std::vector inv = {"A", "Y"}; -+ std::vector tie_lo = {"L"}; -+ std::vector icg = {"ENA", "SE", "CLK", "GCLK"}; -+ bool flop_inverted = true; // the flop's output is QN -+}; -+ -+Pins g_pins; // set by ReadSpec, read by Generate -+ -+// `periphery verilog` with `mode netlist`: the block is the core alone, -+// _core, its ports the module's ports it uses and the nets it -+// shares with the periphery; the periphery is a wrapper module around it, -+// written by WriteVerilog. Generate fills this, WriteVerilog reads it. -+struct WrapperCell -+{ -+ std::string master; -+ std::string name; -+ std::vector> conns; // pin, net -+}; -+struct Wrapper -+{ -+ std::string module; // the RTL module the wrapper stands in for -+ std::string core; // the block: _core -+ std::vector> ports; // the module's -+ std::vector wires; // its nets that are not ports -+ std::vector cells; // the periphery -+ std::vector> core_conns; // port, net -+}; -+Wrapper g_wrapper; -+ -+bool SplitPeriphery(const Spec& s) -+{ -+ return s.periphery == "verilog" && s.mode == "netlist"; -+} -+ -+// Everything the builder needs while it lays cells into rows. -+class Builder -+{ -+ public: -+ Builder(odb::dbDatabase* db, utl::Logger* logger, const Spec& spec) -+ : db_(db), logger_(logger), spec_(spec) -+ { -+ } -+ -+ dbBlock* Run(); -+ -+ private: -+ dbMaster* Master(const std::string& name, const char* role) -+ { -+ dbMaster* m = db_->findMaster(name.c_str()); -+ if (m == nullptr) { -+ Refuse(std::string("cell for ") + role -+ + " not in the loaded LEF: " + name); -+ } -+ return m; -+ } -+ void CheckPins(dbMaster* m, const std::vector& pins) -+ { -+ for (const auto& p : pins) { -+ if (m->findMTerm(p.c_str()) == nullptr) { -+ Refuse("cell " + m->getName() + " has no pin " + p -+ + "; give its pins with `pins ...` in the spec"); -+ } -+ } -+ } -+ dbNet* Net(const std::string& name) -+ { -+ dbNet* n = block_->findNet(name.c_str()); -+ if (n == nullptr) { -+ n = dbNet::create(block_, name.c_str()); -+ } -+ return n; -+ } -+ dbBTerm* Input(const std::string& name) -+ { -+ dbNet* n = Net(name); -+ dbBTerm* t = dbBTerm::create(n, name.c_str()); -+ t->setIoType(odb::dbIoType::INPUT); -+ t->setSigType(odb::dbSigType::SIGNAL); -+ return t; -+ } -+ dbBTerm* Output(const std::string& name, dbNet* net) -+ { -+ dbBTerm* t = dbBTerm::create(net, name.c_str()); -+ t->setIoType(odb::dbIoType::OUTPUT); -+ t->setSigType(odb::dbSigType::SIGNAL); -+ return t; -+ } -+ // A cell dropped into a row cursor: placed left to right, FIRM. -+ struct Cursor -+ { -+ int row = 0; -+ int x = 0; -+ }; -+ dbInst* Place(Cursor& c, -+ dbMaster* m, -+ const std::string& name, -+ const std::vector>& conns) -+ { -+ // Cells are named after the net they drive, with a suffix: Verilog -+ // has one namespace for wires and instances, and yosys refuses a -+ // netlist where a cell and a wire share a name. -+ std::string inst_name = name; -+ if (block_->findNet(name.c_str()) != nullptr) { -+ inst_name += "_g"; -+ } -+ dbInst* inst = dbInst::create(block_, m, inst_name.c_str()); -+ for (const auto& [pin, net] : conns) { -+ odb::dbITerm* it = inst->findITerm(pin.c_str()); -+ if (it == nullptr) { -+ Refuse("cell " + m->getName() + " has no pin " + pin); -+ } -+ it->connect(net); -+ } -+ inst->setOrient(c.row % 2 == 0 ? odb::dbOrientType::R0 -+ : odb::dbOrientType::MX); -+ inst->setLocation(core_x0_ + c.x, core_y0_ + c.row * row_h_); -+ inst->setPlacementStatus(odb::dbPlacementStatus::FIRM); -+ if (periphery_) { -+ periphery_insts_.push_back(inst); -+ } -+ c.x += static_cast(m->getWidth()); -+ max_x_ = std::max(max_x_, c.x); -+ return inst; -+ } -+ // A one-hot select for `bits` address literals and an enable: an AND2 -+ // tree over the literals, placed at the cursor. -+ dbNet* Decode(Cursor& c, -+ const std::string& prefix, -+ const std::vector& literals) -+ { -+ std::vector level = literals; -+ int k = 0; -+ while (level.size() > 1) { -+ std::vector next; -+ for (size_t i = 0; i + 1 < level.size(); i += 2) { -+ dbNet* y = Net(prefix + "_a" + std::to_string(k++)); -+ Place(c, -+ and2_, -+ y->getName(), -+ {{g_pins.and2[0], level[i]}, -+ {g_pins.and2[1], level[i + 1]}, -+ {g_pins.and2[2], y}}); -+ next.push_back(y); -+ } -+ if (level.size() % 2 == 1) { -+ next.push_back(level.back()); -+ } -+ level = next; -+ } -+ return level.front(); -+ } -+ // OR tree over `leaves`, each node placed by a caller-supplied hook so -+ // the tree can run down a column rather than sit in a footer. -+ dbNet* OrTree(const std::string& prefix, -+ const std::vector& leaves, -+ const std::function& where) -+ { -+ std::function rec -+ = [&](int lo, int hi, int& k) -> dbNet* { -+ if (hi - lo == 1) { -+ return leaves[lo]; -+ } -+ int mid = (lo + hi) / 2; -+ dbNet* a = rec(lo, mid, k); -+ dbNet* b = rec(mid, hi, k); -+ dbNet* y = Net(prefix + "_o" + std::to_string(k++)); -+ Place(where(lo, hi), -+ or2_, -+ y->getName(), -+ {{g_pins.or2[0], a}, {g_pins.or2[1], b}, {g_pins.or2[2], y}}); -+ return y; -+ }; -+ int k = 0; -+ return rec(0, static_cast(leaves.size()), k); -+ } -+ // A read bitline: OR over words of (sel & q), in inverting gates. A -+ // word pair is one AOI22, ~(sel_a & q_a | sel_b & q_b), in the pair's -+ // first tile; an odd word out is a NAND2. Over those active-low leaves -+ // a balanced tree alternates NAND2 (low in, high out) and NOR2 (high -+ // in, low out), each node in the second tile of its middle pair, and -+ // the root takes two high inputs with an OR2, so the bitline leaves on -+ // the library's OR2 drive. Where a split leaves the two halves at -+ // different polarities an inverter evens them. One gate level per -+ // pair of words instead of an AND2 and an OR2 per level. -+ struct Polar -+ { -+ dbNet* net; -+ bool low; -+ }; -+ dbNet* Bitline(const std::string& prefix, -+ const std::vector& sel, -+ const std::vector& q, -+ const std::function& tile, -+ const std::vector& words) -+ { -+ const int n = static_cast(q.size()); -+ const int L = (n + 1) / 2; -+ int k = 0; -+ auto first = [&](int l) { return words[2 * l]; }; -+ auto second = [&](int l) { -+ return 2 * l + 1 < n ? words[2 * l + 1] : words[2 * l]; -+ }; -+ std::vector leaf(L); -+ for (int l = 0; l < L; ++l) { -+ dbNet* y = Net(prefix + "_l" + std::to_string(l)); -+ if (2 * l + 1 < n) { -+ Place(tile(first(l)), -+ aoi22_, -+ y->getName(), -+ {{g_pins.aoi22[0], sel[2 * l]}, -+ {g_pins.aoi22[1], q[2 * l]}, -+ {g_pins.aoi22[2], sel[2 * l + 1]}, -+ {g_pins.aoi22[3], q[2 * l + 1]}, -+ {g_pins.aoi22[4], y}}); -+ } else { -+ Place(tile(first(l)), -+ nand2_, -+ y->getName(), -+ {{g_pins.nand2[0], sel[2 * l]}, -+ {g_pins.nand2[1], q[2 * l]}, -+ {g_pins.nand2[2], y}}); -+ } -+ leaf[l] = Polar{y, true}; -+ } -+ auto invert = [&](Polar p, Cursor& c) { -+ dbNet* y = Net(prefix + "_i" + std::to_string(k++)); -+ Place( -+ c, inv_, y->getName(), {{g_pins.inv[0], p.net}, {g_pins.inv[1], y}}); -+ return Polar{y, !p.low}; -+ }; -+ std::function rec -+ = [&](int lo, int hi, bool root) -> Polar { -+ if (hi - lo == 1) { -+ return leaf[lo]; -+ } -+ const int mid = (lo + hi) / 2; -+ Polar a = rec(lo, mid, false); -+ Polar b = rec(mid, hi, false); -+ Cursor& c = tile(second(mid)); -+ if (a.low != b.low) { -+ // the shallower half is the one a level behind -+ if (mid - lo < hi - mid) { -+ a = invert(a, c); -+ } else { -+ b = invert(b, c); -+ } -+ } -+ dbNet* y = Net(prefix + "_o" + std::to_string(k++)); -+ dbMaster* m = a.low ? nand2_ : (root ? or2_ : nor2_); -+ const std::vector& p -+ = a.low ? g_pins.nand2 : (root ? g_pins.or2 : g_pins.nor2); -+ Place(c, m, y->getName(), {{p[0], a.net}, {p[1], b.net}, {p[2], y}}); -+ return Polar{y, !a.low && !root}; -+ }; -+ Polar out = rec(0, L, true); -+ if (out.low) { -+ out = invert(out, tile(second(0))); -+ } -+ return out.net; -+ } -+ // The row of a tile or header with the least in it so far: cells of -+ // different widths pack evenly, which a round robin does not do. -+ static Cursor& Least(std::vector& rows) -+ { -+ return *std::min_element( -+ rows.begin(), rows.end(), [](const Cursor& a, const Cursor& b) { -+ return a.x < b.x; -+ }); -+ } -+ void Pin(dbBTerm* t, odb::dbTechLayer* layer, int x, int y) -+ { -+ odb::dbBPin* bp = odb::dbBPin::create(t); -+ int w = std::max(static_cast(layer->getWidth()), 1); -+ odb::dbBox::create(bp, layer, x - w / 2, y - w / 2, x + w / 2, y + w / 2); -+ bp->setPlacementStatus(odb::dbPlacementStatus::FIRM); -+ } -+ -+ // `periphery verilog` with `mode netlist`: the periphery leaves the -+ // block for the wrapper module (g_wrapper); a net it shares with the -+ // core becomes a port of the core, an input where the periphery drives -+ // it, an output where the core does. A module port only the periphery -+ // uses leaves the core. -+ void SplitCore() -+ { -+ std::set periphery; // by id: odb objects have no order -+ for (dbInst* inst : periphery_insts_) { -+ periphery.insert(inst->getId()); -+ } -+ auto ref = [](dbNet* n) { -+ return n->getBTerms().begin() != n->getBTerms().end() -+ ? std::string((*n->getBTerms().begin())->getName()) -+ : "\\" + n->getName() + " "; -+ }; -+ g_wrapper.module = spec_.module; -+ g_wrapper.core = block_->getName(); -+ for (odb::dbBTerm* t : block_->getBTerms()) { -+ g_wrapper.ports.emplace_back(t->getName(), t->getIoType()); -+ } -+ std::vector dropped; -+ std::vector> shared; -+ for (dbNet* n : block_->getNets()) { -+ if (n->getSigType() == odb::dbSigType::POWER -+ || n->getSigType() == odb::dbSigType::GROUND) { -+ continue; -+ } -+ bool in_periphery = false; -+ bool in_core = false; -+ bool periphery_drives = false; -+ for (odb::dbITerm* it : n->getITerms()) { -+ const bool p = periphery.count(it->getInst()->getId()) > 0; -+ in_periphery |= p; -+ in_core |= !p; -+ if (p && it->getIoType() == odb::dbIoType::OUTPUT) { -+ periphery_drives = true; -+ } -+ } -+ const bool port = n->getBTerms().begin() != n->getBTerms().end(); -+ if (port) { -+ if (in_core) { -+ const std::string name = (*n->getBTerms().begin())->getName(); -+ g_wrapper.core_conns.emplace_back(name, name); -+ } else { -+ for (odb::dbBTerm* t : n->getBTerms()) { -+ dropped.push_back(t); -+ } -+ } -+ continue; -+ } -+ if (in_periphery) { -+ g_wrapper.wires.push_back(ref(n)); -+ } -+ if (in_periphery && in_core) { -+ shared.emplace_back(n, periphery_drives ? odb::dbIoType::INPUT -+ : odb::dbIoType::OUTPUT); -+ } -+ } -+ for (dbInst* inst : periphery_insts_) { -+ WrapperCell cell{inst->getMaster()->getName(), inst->getName(), {}}; -+ for (odb::dbITerm* it : inst->getITerms()) { -+ if (it->getNet() != nullptr -+ && it->getNet()->getSigType() != odb::dbSigType::POWER -+ && it->getNet()->getSigType() != odb::dbSigType::GROUND) { -+ cell.conns.emplace_back(it->getMTerm()->getName(), ref(it->getNet())); -+ } -+ } -+ g_wrapper.cells.push_back(std::move(cell)); -+ } -+ for (auto& [n, io] : shared) { -+ dbBTerm* t = dbBTerm::create(n, n->getName().c_str()); -+ t->setIoType(io); -+ t->setSigType(odb::dbSigType::SIGNAL); -+ g_wrapper.core_conns.emplace_back(n->getName(), ref(n)); -+ } -+ for (odb::dbBTerm* t : dropped) { -+ std::vector pins(t->getBPins().begin(), -+ t->getBPins().end()); -+ for (odb::dbBPin* bp : pins) { -+ odb::dbBPin::destroy(bp); -+ } -+ odb::dbBTerm::destroy(t); -+ } -+ for (dbInst* inst : periphery_insts_) { -+ dbInst::destroy(inst); -+ } -+ periphery_insts_.clear(); -+ std::vector empty; -+ for (dbNet* n : block_->getNets()) { -+ if (n->getITerms().empty() && n->getBTerms().empty()) { -+ empty.push_back(n); -+ } -+ } -+ for (dbNet* n : empty) { -+ dbNet::destroy(n); -+ } -+ } -+ -+ odb::dbDatabase* db_; -+ utl::Logger* logger_; -+ const Spec& spec_; -+ dbBlock* block_ = nullptr; -+ odb::dbSite* site_ = nullptr; -+ odb::dbTechLayer* layer_h_ = nullptr; // left/right edge pins -+ odb::dbTechLayer* layer_v_ = nullptr; // top/bottom edge pins -+ dbMaster* flop_ = nullptr; -+ dbMaster* store_ = nullptr; // the storage flop: flop_, or flop_r -+ dbMaster* tie_hi_ = nullptr; -+ dbMaster* and2_ = nullptr; -+ dbMaster* or2_ = nullptr; -+ dbMaster* ao22_ = nullptr; -+ dbMaster* aoi22_ = nullptr; -+ dbMaster* nand2_ = nullptr; -+ dbMaster* nor2_ = nullptr; -+ dbMaster* inv_ = nullptr; -+ dbMaster* tap_ = nullptr; -+ dbMaster* tie_lo_ = nullptr; -+ dbMaster* icg_ = nullptr; -+ int dbu_ = 1000; -+ int site_w_ = 0; -+ int row_h_ = 0; -+ int core_x0_ = 0; -+ int core_y0_ = 0; -+ int pin_w_ = 0; -+ int max_x_ = 0; -+ // One entry per (word, bit) tile in row-major order: its row cursors, -+ // which the read OR trees keep filling after the tile's own cells, and -+ // the x where the tile ends, checked once the trees are in. -+ struct Tile -+ { -+ std::vector rows; -+ int x_end = 0; -+ }; -+ std::vector tiles_; -+ // The periphery: the address band and each word's decode. In netlist -+ // mode these are left unplaced (see Run). -+ bool periphery_ = false; -+ std::vector periphery_insts_; -+}; -+ -+dbBlock* Builder::Run() -+{ -+ const Spec& s = spec_; -+ if (s.words < 2 || s.bits < 1 || s.read.empty() || s.write.empty()) { -+ Refuse( -+ "a register file needs at least 2 words, 1 bit, 1 read and 1 " -+ "write port"); -+ } -+ flop_ = Master(s.cells.flop, "flop"); -+ and2_ = Master(s.cells.and2, "and2"); -+ or2_ = Master(s.cells.or2, "or2"); -+ ao22_ = Master(s.cells.ao22, "ao22"); -+ aoi22_ = Master(s.cells.aoi22, "aoi22"); -+ nand2_ = Master(s.cells.nand2, "nand2"); -+ nor2_ = Master(s.cells.nor2, "nor2"); -+ inv_ = Master(s.cells.inv, "inv"); -+ tap_ = s.cells.tap.empty() ? nullptr : Master(s.cells.tap, "tap"); -+ tie_lo_ = s.cells.tie_lo.empty() ? nullptr : Master(s.cells.tie_lo, "tie_lo"); -+ CheckPins(flop_, g_pins.flop); -+ CheckPins(and2_, g_pins.and2); -+ CheckPins(or2_, g_pins.or2); -+ CheckPins(ao22_, g_pins.ao22); -+ CheckPins(aoi22_, g_pins.aoi22); -+ CheckPins(nand2_, g_pins.nand2); -+ CheckPins(nor2_, g_pins.nor2); -+ CheckPins(inv_, g_pins.inv); -+ const bool gated = s.write_style == "clock_gate"; -+ if (gated) { -+ icg_ = Master(s.cells.icg, "icg"); -+ CheckPins(icg_, g_pins.icg); -+ } -+ store_ = flop_; -+ if (s.async_reset) { -+ store_ = Master(s.cells.flop_r, "flop_r"); -+ CheckPins(store_, g_pins.flop_r); -+ tie_hi_ = Master(s.cells.tie_hi, "tie_hi"); -+ CheckPins(tie_hi_, g_pins.tie_hi); -+ } -+ -+ odb::dbTech* tech = db_->getTech(); -+ site_ = flop_->getSite(); -+ if (site_ == nullptr) { -+ Refuse("flop " + flop_->getName() + " has no site"); -+ } -+ site_w_ = site_->getWidth(); -+ row_h_ = site_->getHeight(); -+ layer_h_ = tech->findLayer(s.pin_layer_h.c_str()); -+ layer_v_ = tech->findLayer(s.pin_layer_v.c_str()); -+ if (layer_h_ == nullptr || layer_v_ == nullptr) { -+ Refuse("pin layers not in the tech LEF: " + s.pin_layer_h + " " -+ + s.pin_layer_v); -+ } -+ pin_w_ = std::max( -+ static_cast(std::max(layer_h_->getWidth(), layer_v_->getWidth())), -+ 1); -+ -+ odb::dbChip* chip = db_->getChip(); -+ if (chip == nullptr) { -+ chip = odb::dbChip::create(db_, tech, s.module.c_str()); -+ } -+ if (chip->getBlock() != nullptr) { -+ Refuse("the database already has a top block (" -+ + chip->getBlock()->getName() + "); one generation per database"); -+ } -+ g_wrapper = Wrapper{}; -+ const std::string block_name -+ = SplitPeriphery(s) ? s.module + "_core" : s.module; -+ block_ = dbBlock::create(chip, block_name.c_str()); -+ if (block_ == nullptr) { -+ Refuse("could not create block " + s.module); -+ } -+ block_->setDefUnits(tech->getLefUnits()); -+ dbu_ = tech->getLefUnits(); -+ -+ const int W = static_cast(s.write.size()); -+ const int R = static_cast(s.read.size()); -+ const int A = AddrBits(s.words); -+ -+ // ---- ports and their nets ------------------------------------------ -+ dbNet* clock = Net(s.clock); -+ Input(s.clock); -+ if (!s.reset.empty()) { -+ // Chisel gives every module a reset; a register file without one -+ // still has the port. It exists on the macro, connected to nothing, -+ // unless `async_reset` makes it the storage flops' reset. -+ Input(s.reset); -+ } -+ for (const auto& u : s.unused) { -+ Input(u); -+ } -+ // Banks first: a banked read port has one address per bank, of the -+ // bank-local width. -+ const int banks = std::max(s.banks, 1); -+ if (s.words % banks != 0) { -+ Refuse("words (" + std::to_string(s.words) -+ + ") is not a multiple of banks (" + std::to_string(banks) + ")"); -+ } -+ const int words_per_bank = s.words / banks; -+ const int A_bank = AddrBits(words_per_bank); -+ const bool interleaved = s.bank_order == "interleaved"; -+ auto bank_of -+ = [&](int n) { return interleaved ? n % banks : n / words_per_bank; }; -+ auto local_of -+ = [&](int n) { return interleaved ? n / banks : n % words_per_bank; }; -+ if (s.zero_word >= s.words || (s.zero_word >= 0 && words_per_bank < 2)) { -+ Refuse("zero_word " + std::to_string(s.zero_word) -+ + " is not a word of a bank that keeps another"); -+ } -+ // Banks in a grid: bank k stands in column k % bank_cols, bank row -+ // k / bank_cols, bank rows stacked upward from the footer. -+ const int bank_cols = s.bank_columns > 0 ? s.bank_columns : banks; -+ if (bank_cols > banks || banks % bank_cols != 0) { -+ Refuse("bank_columns (" + std::to_string(bank_cols) -+ + ") does not divide banks (" + std::to_string(banks) + ")"); -+ } -+ const int bank_rows = banks / bank_cols; -+ // Bit folds: band f holds bits [f * bits_per_fold, (f + 1) * bits_per_fold) -+ // of every word, stacked above band f - 1 inside the bank; the last -+ // band is short when the folds do not divide the bits. -+ const int folds = std::max(s.bit_folds, 1); -+ if (folds > s.bits) { -+ Refuse("bit_folds (" + std::to_string(folds) + ") exceeds bits (" -+ + std::to_string(s.bits) + ")"); -+ } -+ const int bits_per_fold = (s.bits + folds - 1) / folds; -+ for (int r = 0; r < R; ++r) { -+ if (s.read[r].banked() -+ && static_cast(s.read[r].bank_addr.size()) != banks) { -+ Refuse("read port " + std::to_string(r) + " names " -+ + std::to_string(s.read[r].bank_addr.size()) -+ + " banks, the array has " + std::to_string(banks)); -+ } -+ } -+ // raddr[r][k] is bank k's literals for a banked port; raddr[r][0] the -+ // one address of a plain port. -+ std::vector>> raddr(R); -+ std::vector> waddr(W), wdata(W); -+ std::vector wen(W, nullptr); -+ for (int r = 0; r < R; ++r) { -+ if (s.read[r].banked()) { -+ raddr[r].resize(banks); -+ for (int k = 0; k < banks; ++k) { -+ for (int i = 0; i < A_bank; ++i) { -+ raddr[r][k].push_back(Net(Bit(s.read[r].bank_addr[k], i))); -+ Input(Bit(s.read[r].bank_addr[k], i)); -+ } -+ } -+ } else { -+ raddr[r].resize(1); -+ for (int i = 0; i < A; ++i) { -+ raddr[r][0].push_back(Net(Bit(s.read[r].addr, i))); -+ Input(Bit(s.read[r].addr, i)); -+ } -+ } -+ } -+ for (int w = 0; w < W; ++w) { -+ for (int i = 0; i < A; ++i) { -+ waddr[w].push_back(Net(Bit(s.write[w].addr, i))); -+ Input(Bit(s.write[w].addr, i)); -+ } -+ for (int b = 0; b < s.bits; ++b) { -+ wdata[w].push_back(Net(Bit(s.write[w].data, b))); -+ Input(Bit(s.write[w].data, b)); -+ } -+ if (!s.write[w].en.empty()) { -+ wen[w] = Net(s.write[w].en); -+ Input(s.write[w].en); -+ } -+ } -+ dbNet* vdd = Net("VDD"); -+ vdd->setSigType(odb::dbSigType::POWER); -+ vdd->setSpecial(); -+ dbNet* vss = Net("VSS"); -+ vss->setSigType(odb::dbSigType::GROUND); -+ vss->setSpecial(); -+ -+ // ---- geometry -------------------------------------------------------- -+ // A word is `rows_per_word` standard rows tall; a bit column holds one -+ // tile per word. The header column to the left holds the decode for -+ // that word: R read selects, W write selects, the hold term. -+ // -+ // Cells per tile: flop, inverter (Q from QN), W-way write mux as AO22 -+ // pairs and an OR2 tree, and per read port one cell of that port's -+ // bitline: a word pair's AOI22 leaf in the pair's first tile, a node -+ // of the NAND2/NOR2 tree over the leaves in its second (see the read -+ // bitlines below). A fix-up inverter rides with a node. -+ // W + 1 terms (the writes and the hold) in pairs: AO22s, an odd last -+ // term an AND2 -+ // Clock-gated, the hold term is gone; one write port leaves no mux. -+ const int write_terms = W + (gated ? 0 : 1); -+ const int write_pairs = write_terms > 1 ? (write_terms + 1) / 2 : 0; -+ const int read_node_w = static_cast( -+ std::max({nand2_->getWidth(), nor2_->getWidth(), or2_->getWidth()}) -+ + inv_->getWidth()); -+ // A tile holds a leaf or a node per port; the odd word out of a bank -+ // with an odd count holds its NAND2 leaf and a node. -+ const int read_cell_w -+ = std::max({static_cast(aoi22_->getWidth()), -+ read_node_w, -+ static_cast(nand2_->getWidth() -+ + std::max({nand2_->getWidth(), -+ nor2_->getWidth(), -+ or2_->getWidth()}))}); -+ const int tile_cells_w = static_cast( -+ store_->getWidth() + inv_->getWidth() + write_pairs * ao22_->getWidth() -+ + std::max(write_pairs - 1, 0) * or2_->getWidth() + R * read_cell_w); -+ int rows_per_word = 1; -+ // Keep a tile near square-ish: at most ~40 sites wide. -+ while (tile_cells_w / rows_per_word > 40 * site_w_ && rows_per_word < 8) { -+ rows_per_word *= 2; -+ } -+ // Rows are filled least-first, so a row is at most one widest cell over -+ // the average; the header carries that slack. -+ const int widest = static_cast(std::max({store_->getWidth(), -+ ao22_->getWidth(), -+ aoi22_->getWidth(), -+ or2_->getWidth(), -+ and2_->getWidth()})); -+ // A tile is as wide as its fullest row once its cells are in, in the -+ // order the builder drops them: the flop, Q's inverter, the write mux, -+ // then a bitline cell per port. The flop alone is most of a row, so -+ // an average-plus-widest-cell estimate leaves a third of the array empty. -+ int tile_w = 0; -+ { -+ std::vector fill(rows_per_word, 0); -+ auto drop -+ = [&](int w) { *std::min_element(fill.begin(), fill.end()) += w; }; -+ drop(static_cast(store_->getWidth())); -+ if (g_pins.flop_inverted) { -+ drop(static_cast(inv_->getWidth())); -+ } -+ for (int i = 0; i < write_pairs; ++i) { -+ drop(static_cast(ao22_->getWidth())); -+ } -+ for (int i = 0; i + 1 < write_pairs; ++i) { -+ drop(static_cast(or2_->getWidth())); -+ } -+ for (int r = 0; r < R; ++r) { -+ drop(read_cell_w); -+ } -+ tile_w = (*std::max_element(fill.begin(), fill.end()) + site_w_ - 1) -+ / site_w_ * site_w_; -+ } -+ // Header: per word, (R+W) decodes of (A+1) literals as AND2 trees, the -+ // address inverters live above the array. hold_n = ~(OR of write -+ // selects), or the word's clock gate enabled by that OR. -+ const int header_cells_w = static_cast( -+ (R + W) * A * and2_->getWidth() + (W - 1) * or2_->getWidth() -+ + (gated ? icg_->getWidth() : inv_->getWidth()) -+ + (s.write_priority == "last" -+ ? (W - 1) -+ * (inv_->getWidth() + and2_->getWidth() + or2_->getWidth()) -+ : 0) -+ + (s.async_reset -+ ? tie_hi_->getWidth() + (s.reset_active_low ? 0 : inv_->getWidth()) -+ : 0)); -+ const int header_w = ((header_cells_w + rows_per_word - 1) / rows_per_word -+ + widest + site_w_ - 1) -+ / site_w_ * site_w_; -+ // A service column every `tap_columns` bit columns: the tap cell and -+ // then `service_sites` empty sites on every row. The placement is -+ // legal without them; what needs the room is what comes after -- the -+ // clock tree's buffers and any repair -- and the slack inside a tile -+ // is a few sites at a time, which a BUFx24 cannot use. Contiguous free -+ // sites next to the flops are where a clock buffer wants to be. In -+ // netlist mode the block dissolves into the parent's rows before the -+ // clock tree, whose buffers go wherever the parent has room: none by -+ // default. -+ const int service_sites -+ = s.service_sites >= 0 ? s.service_sites : (s.mode == "netlist" ? 0 : 40); -+ const int tap_w = (tap_ ? static_cast(tap_->getWidth()) : 0) -+ + service_sites * site_w_; -+ const int tap_every = std::max(s.tap_columns, 1); -+ const int tap_cols = (tap_ || service_sites > 0) -+ ? (bits_per_fold + tap_every - 1) / tap_every -+ : 0; -+ // Banks: the word column folded into `banks` columns, `bank_cols` of -+ // them side by side and the rest stacked, each with its own header and -+ // service columns, so a 256-word file is not ten times taller than it -+ // is wide and a 128-bit one not ten times wider than tall. A plain read -+ // port's bitline is one OR tree per bank and a final OR across banks in -+ // a footer band; a banked port's bank trees are its outputs and need no -+ // footer. -+ const int bank_w = header_w + bits_per_fold * tile_w + tap_cols * tap_w; -+ // A bank is `folds` bands tall, each band every word of the bank. -+ const int band_h_rows = words_per_bank * rows_per_word; -+ const int bank_h_rows = folds * band_h_rows; -+ int plain_reads = 0; -+ for (int r = 0; r < R; ++r) { -+ plain_reads += s.read[r].banked() ? 0 : 1; -+ } -+ // Footer: (banks-1) OR2 per read port per bit, as many rows as it takes. -+ const int core_w = bank_cols * bank_w; -+ const int footer_cells_w = banks > 1 -+ ? (banks - 1) * plain_reads * s.bits -+ * static_cast(or2_->getWidth()) -+ : 0; -+ const int footer_rows -+ = footer_cells_w > 0 ? (footer_cells_w + core_w - 1) / core_w + 1 : 0; -+ // The address band above the array: an inverter per address literal, -+ // and with a read latency a flop ahead of each read one, each cell with -+ // a spare site after it; as many rows as that takes. -+ int read_addr_bits = 0; -+ for (int r = 0; r < R; ++r) { -+ read_addr_bits += s.read[r].banked() ? banks * A_bank : A; -+ } -+ const int inv_cell_w = static_cast(inv_->getWidth()) + site_w_; -+ const int reg_cell_w -+ = s.read_latency > 0 ? static_cast(flop_->getWidth()) + site_w_ : 0; -+ const int band_w -+ = read_addr_bits * (inv_cell_w + reg_cell_w) + W * A * inv_cell_w; -+ const int inv_rows = std::max(1, (band_w + core_w - 1) / core_w); -+ const int total_rows = footer_rows + bank_rows * bank_h_rows + inv_rows; -+ -+ // Core at a site multiple in from the die so a parent's ring fits. -+ core_x0_ = 10 * site_w_; -+ core_y0_ = 2 * row_h_; -+ const int die_w = core_w + 20 * site_w_; -+ const int die_h = total_rows * row_h_ + 4 * row_h_; -+ block_->setDieArea(odb::Rect(0, 0, die_w, die_h)); -+ for (int r = 0; r < total_rows; ++r) { -+ std::string rn = "ROW_" + std::to_string(r); -+ odb::dbRow::create( -+ block_, -+ rn.c_str(), -+ site_, -+ core_x0_, -+ core_y0_ + r * row_h_, -+ r % 2 == 0 ? odb::dbOrientType::R0 : odb::dbOrientType::MX, -+ odb::dbRowDir::HORIZONTAL, -+ core_w / site_w_, -+ site_w_); -+ } -+ -+ // ---- address inverters, top band ------------------------------------ -+ // Periphery: their inputs are the address ports, their outputs the -+ // widest nets of the block. In netlist mode they are left unplaced for -+ // the parent (see the end of Run). In a macro, the macro's own repair -+ // may upsize one, and a cell that may be resized is one that may move: -+ // PLACED, not FIRM, with a spare site after each for INVx1 to INVx2. -+ std::vector>> raddr_n(R); -+ std::vector> waddr_n(W); -+ periphery_ = true; -+ { -+ Cursor c{total_rows - 1, 0}; -+ // A cell and its spare site, on the next band row down if this one -+ // is full. -+ auto band = [&](dbMaster* m, -+ const std::string& name, -+ const std::vector>& conns) { -+ if (c.x + static_cast(m->getWidth()) > core_w) { -+ c = Cursor{c.row - 1, 0}; -+ } -+ Place(c, m, name, conns) -+ ->setPlacementStatus(odb::dbPlacementStatus::PLACED); -+ c.x += site_w_; -+ }; -+ for (int r = 0; r < R; ++r) { -+ raddr_n[r].resize(raddr[r].size()); -+ for (size_t k = 0; k < raddr[r].size(); ++k) { -+ for (size_t i = 0; i < raddr[r][k].size(); ++i) { -+ const std::string base -+ = "rd" + std::to_string(r) + "_k" + std::to_string(k); -+ if (s.read_latency > 0) { -+ // The registered address: the flop's QN is the inverted -+ // literal, one inverter gives the true one (the other way -+ // round for a Q flop). The decode reads only these. -+ const std::string reg = s.read_reg_name.empty() -+ ? base + "_areg" + std::to_string(i) -+ : Fmt(s.read_reg_name, -+ {{"port", r}, -+ {"bank", static_cast(k)}, -+ {"bit", static_cast(i)}}); -+ dbNet* out = Net(base + "_aq" + std::to_string(i)); -+ band(flop_, -+ reg, -+ {{g_pins.flop[0], raddr[r][k][i]}, -+ {g_pins.flop[1], clock}, -+ {g_pins.flop[2], out}}); -+ dbNet* other = Net(base + "_ai" + std::to_string(i)); -+ band(inv_, -+ other->getName(), -+ {{g_pins.inv[0], out}, {g_pins.inv[1], other}}); -+ raddr[r][k][i] = g_pins.flop_inverted ? other : out; -+ raddr_n[r][k].push_back(g_pins.flop_inverted ? out : other); -+ continue; -+ } -+ dbNet* y = Net(base + "_na" + std::to_string(i)); -+ band(inv_, -+ y->getName(), -+ {{g_pins.inv[0], raddr[r][k][i]}, {g_pins.inv[1], y}}); -+ raddr_n[r][k].push_back(y); -+ } -+ } -+ } -+ for (int w = 0; w < W; ++w) { -+ for (int i = 0; i < A; ++i) { -+ dbNet* y = Net("wr" + std::to_string(w) + "_na" + std::to_string(i)); -+ band(inv_, -+ y->getName(), -+ {{g_pins.inv[0], waddr[w][i]}, {g_pins.inv[1], y}}); -+ waddr_n[w].push_back(y); -+ } -+ } -+ if (c.row < total_rows - inv_rows) { -+ Refuse("address band overflow: widen the band estimate"); -+ } -+ } -+ periphery_ = false; -+ -+ // ---- per band and word: header decode, then tiles across the bits ---- -+ // The decode is per (band, word): a band is its own rows, so the word -+ // selects it needs are made again beside it. Cheap next to the tiles. -+ std::vector> rsel(R, std::vector(s.words)); -+ std::vector> wsel(W, std::vector(s.words)); -+ std::vector hold(s.words); -+ std::vector gclk(s.words, nullptr); -+ // Read bitline inputs per (r, b), down the column: each word's select -+ // and stored value, paired into AOI22 leaves once all tiles are in. -+ std::vector>> leaves( -+ R, std::vector>(s.bits)); -+ std::vector>> leaf_sel( -+ R, std::vector>(s.bits)); -+ // The word each leaf reads, for its bank and the tile its OR node sits in. -+ std::vector>> leaf_word( -+ R, std::vector>(s.bits)); -+ tiles_.assign(static_cast(s.words) * s.bits, Tile{}); -+ -+ auto literals = -+ [&](const std::vector& a, const std::vector& an, int n) { -+ std::vector l; -+ for (size_t i = 0; i < a.size(); ++i) { -+ l.push_back(((n >> i) & 1) ? a[i] : an[i]); -+ } -+ return l; -+ }; -+ -+ for (int f = 0; f < folds; ++f) { -+ for (int n = 0; n < s.words; ++n) { -+ if (n == s.zero_word) { -+ continue; // no storage, no selects: it reads 0, a write is dropped -+ } -+ const int bank = bank_of(n); -+ const int row0 = footer_rows + (bank / bank_cols) * bank_h_rows -+ + f * band_h_rows + local_of(n) * rows_per_word; -+ const int bank_x0 = (bank % bank_cols) * bank_w; -+ // Header column, spread over this word's rows. -+ std::vector hc; -+ for (int k = 0; k < rows_per_word; ++k) { -+ hc.push_back(Cursor{row0 + k, bank_x0}); -+ } -+ auto hcur = [&]() -> Cursor& { return Least(hc); }; -+ periphery_ = true; -+ std::string wn = "w" + std::to_string(n) -+ + (folds > 1 ? "_f" + std::to_string(f) : ""); -+ for (int r = 0; r < R; ++r) { -+ const bool banked = s.read[r].banked(); -+ rsel[r][n] = Decode(hcur(), -+ wn + "_rsel" + std::to_string(r), -+ literals(raddr[r][banked ? bank : 0], -+ raddr_n[r][banked ? bank : 0], -+ banked ? local_of(n) : n)); -+ } -+ std::vector wsels; -+ for (int w = 0; w < W; ++w) { -+ std::vector l = literals(waddr[w], waddr_n[w], n); -+ if (wen[w] != nullptr) { -+ l.push_back(wen[w]); -+ } -+ wsel[w][n] = Decode(hcur(), wn + "_wsel" + std::to_string(w), l); -+ wsels.push_back(wsel[w][n]); -+ } -+ if (s.write_priority == "last" && W > 1) { -+ // A later port wins: each write select masked by the later ones'. -+ // The clock gate and hold still see every write (wsels). -+ dbNet* later = wsel[W - 1][n]; -+ for (int w = W - 2; w >= 0; --w) { -+ const std::string k = wn + "_wp" + std::to_string(w); -+ dbNet* later_n = Net(k + "_ln"); -+ Place(hcur(), -+ inv_, -+ later_n->getName(), -+ {{g_pins.inv[0], later}, {g_pins.inv[1], later_n}}); -+ dbNet* masked = Net(k + "_sel"); -+ Place(hcur(), -+ and2_, -+ masked->getName(), -+ {{g_pins.and2[0], wsel[w][n]}, -+ {g_pins.and2[1], later_n}, -+ {g_pins.and2[2], masked}}); -+ if (w > 0) { -+ dbNet* any_later = Net(k + "_l"); -+ Place(hcur(), -+ or2_, -+ any_later->getName(), -+ {{g_pins.or2[0], later}, -+ {g_pins.or2[1], wsel[w][n]}, -+ {g_pins.or2[2], any_later}}); -+ later = any_later; -+ } -+ wsel[w][n] = masked; -+ } -+ } -+ // hold = ~(wsel0 | wsel1 | ...): the word keeps its value. -+ dbNet* any_write -+ = wsels.size() == 1 -+ ? wsels[0] -+ : OrTree(wn + "_anyw", wsels, [&](int, int) -> Cursor& { -+ return hcur(); -+ }); -+ if (gated) { -+ // The word's clock runs only on a write. SE is the latch's other -+ // enable (ENA | SE); tied to the same select it changes nothing. -+ gclk[n] = Net(wn + "_gclk"); -+ Place(hcur(), -+ icg_, -+ wn + "_icg", -+ {{g_pins.icg[0], any_write}, -+ {g_pins.icg[1], any_write}, -+ {g_pins.icg[2], clock}, -+ {g_pins.icg[3], gclk[n]}}); -+ } else { -+ hold[n] = Net(wn + "_hold"); -+ Place(hcur(), -+ inv_, -+ hold[n]->getName(), -+ {{g_pins.inv[0], any_write}, {g_pins.inv[1], hold[n]}}); -+ } -+ // The word's reset and set, for `async_reset`: an active-high reset -+ // inverted here, and the set tied off, one of each per word so no -+ // net fans out past one word's bits. -+ dbNet* resetn = nullptr; -+ dbNet* setn = nullptr; -+ if (s.async_reset) { -+ resetn = Net(s.reset); -+ if (!s.reset_active_low) { -+ resetn = Net(wn + "_resetn"); -+ Place(hcur(), -+ inv_, -+ resetn->getName(), -+ {{g_pins.inv[0], Net(s.reset)}, {g_pins.inv[1], resetn}}); -+ } -+ setn = Net(wn + "_setn"); -+ Place(hcur(), tie_hi_, setn->getName(), {{g_pins.tie_hi[0], setn}}); -+ } -+ periphery_ = false; -+ for (auto& c : hc) { -+ if (c.x > bank_x0 + header_w) { -+ Refuse("header column overflow at word " + std::to_string(n) -+ + ": widen the header estimate"); -+ } -+ } -+ -+ // Tiles, this band's bits. -+ int x = bank_x0 + header_w; -+ for (int bl = 0; bl < bits_per_fold && f * bits_per_fold + bl < s.bits; -+ ++bl) { -+ const int b = f * bits_per_fold + bl; -+ if (tap_cols > 0 && bl % tap_every == 0) { -+ if (tap_) { -+ for (int k = 0; k < rows_per_word; ++k) { -+ Cursor tc{row0 + k, x}; -+ Place(tc, -+ tap_, -+ "tap_" + wn + "_c" + std::to_string(bl / tap_every) + "_r" -+ + std::to_string(k), -+ {}); -+ } -+ } -+ x += tap_w; // the rest of the service column stays empty -+ } -+ std::string tn = wn + "_b" + std::to_string(b); -+ std::vector tc; -+ for (int k = 0; k < rows_per_word; ++k) { -+ tc.push_back(Cursor{row0 + k, x}); -+ } -+ auto tcur = [&]() -> Cursor& { return Least(tc); }; -+ -+ // Storage. The flop's QN holds ~value; Q is recovered by an inverter. -+ // One gated write port: D is the write data bit. -+ dbNet* d = gated && W == 1 ? wdata[0][b] : Net(tn + "_d"); -+ dbNet* qn = Net(tn + "_qn"); -+ dbNet* q = g_pins.flop_inverted ? Net(tn + "_q") : qn; -+ const std::string ff_name -+ = s.store_name.empty() -+ ? tn + "_ff" -+ : Fmt(s.store_name, {{"word", n}, {"bit", b}}); -+ if (s.async_reset) { -+ Place(tcur(), -+ store_, -+ ff_name, -+ {{g_pins.flop_r[0], d}, -+ {g_pins.flop_r[1], gated ? gclk[n] : clock}, -+ {g_pins.flop_r[2], resetn}, -+ {g_pins.flop_r[3], setn}, -+ {g_pins.flop_r[4], qn}}); -+ } else { -+ Place(tcur(), -+ flop_, -+ ff_name, -+ {{g_pins.flop[0], d}, -+ {g_pins.flop[1], gated ? gclk[n] : clock}, -+ {g_pins.flop[2], qn}}); -+ } -+ if (g_pins.flop_inverted) { -+ Place(tcur(), -+ inv_, -+ tn + "_qinv", -+ {{g_pins.inv[0], qn}, {g_pins.inv[1], q}}); -+ } -+ // Write mux: d = OR_w (wsel_w & wdata_w[b]) | (hold & q), as AO22 -+ // pairs then an OR2 tree. -+ std::vector> terms; -+ for (int w = 0; w < W; ++w) { -+ terms.emplace_back(wsel[w][n], wdata[w][b]); -+ } -+ if (!gated) { -+ terms.emplace_back(hold[n], q); -+ } -+ std::vector partial; -+ for (size_t i = 0; write_pairs > 0 && i < terms.size(); i += 2) { -+ dbNet* y = Net(tn + "_wm" + std::to_string(i / 2)); -+ if (i + 1 < terms.size()) { -+ Place(tcur(), -+ ao22_, -+ y->getName(), -+ {{g_pins.ao22[0], terms[i].first}, -+ {g_pins.ao22[1], terms[i].second}, -+ {g_pins.ao22[2], terms[i + 1].first}, -+ {g_pins.ao22[3], terms[i + 1].second}, -+ {g_pins.ao22[4], y}}); -+ } else { -+ Place(tcur(), -+ and2_, -+ y->getName(), -+ {{g_pins.and2[0], terms[i].first}, -+ {g_pins.and2[1], terms[i].second}, -+ {g_pins.and2[2], y}}); -+ } -+ partial.push_back(y); -+ } -+ dbNet* mux = partial.empty() ? d -+ : partial.size() == 1 -+ ? partial[0] -+ : OrTree(tn + "_wo", -+ partial, -+ [&](int, int) -> Cursor& { return tcur(); }); -+ // The OR tree's root must be the flop's D net: alias by re-connecting. -+ if (mux != d) { -+ // Move every iterm on `mux` to `d`. -+ std::vector its(mux->getITerms().begin(), -+ mux->getITerms().end()); -+ for (auto* it : its) { -+ it->disconnect(); -+ it->connect(d); -+ } -+ dbNet::destroy(mux); -+ } -+ // This word's inputs to each port's bitline. -+ for (int r = 0; r < R; ++r) { -+ leaves[r][b].push_back(q); -+ leaf_sel[r][b].push_back(rsel[r][n]); -+ leaf_word[r][b].push_back(n); -+ } -+ // Keep the row cursors: the read OR trees fill the tile's leftover. -+ tiles_[static_cast(n) * s.bits + b] = Tile{tc, x + tile_w}; -+ x += tile_w; -+ } -+ } -+ } -+ -+ // ---- read bitlines: OR trees down each column ------------------------ -+ // A node covering words [lo, hi) is dropped into the tile of word -+ // (lo+hi)/2 in that bit column, round-robin over its rows. -+ std::vector> rdata(R); -+ std::vector footer; -+ for (int k = 0; k < footer_rows; ++k) { -+ footer.push_back(Cursor{k, 0}); -+ } -+ for (int r = 0; r < R; ++r) { -+ for (int b = 0; b < s.bits; ++b) { -+ std::string prefix = "rd" + std::to_string(r) + "_b" + std::to_string(b); -+ std::vector bank_roots; -+ for (int k = 0; k < banks; ++k) { -+ // The bank's words in entry order; ascending words keep it. -+ std::vector bank_q, bank_sel; -+ std::vector bank_words; -+ for (size_t i = 0; i < leaves[r][b].size(); ++i) { -+ if (bank_of(leaf_word[r][b][i]) == k) { -+ bank_q.push_back(leaves[r][b][i]); -+ bank_sel.push_back(leaf_sel[r][b][i]); -+ bank_words.push_back(leaf_word[r][b][i]); -+ } -+ } -+ bank_roots.push_back(Bitline( -+ prefix + "_k" + std::to_string(k), -+ bank_sel, -+ bank_q, -+ [&](int word) -> Cursor& { -+ return Least(tiles_[word * s.bits + b].rows); -+ }, -+ bank_words)); -+ } -+ // Each root becomes an output net with the RTL's name: one per -+ // bank for a banked port, one after the footer OR for a plain one. -+ auto emit = [&](dbNet* root, const std::string& name) { -+ std::vector its(root->getITerms().begin(), -+ root->getITerms().end()); -+ dbNet* out = Net(name); -+ for (auto* it : its) { -+ it->disconnect(); -+ it->connect(out); -+ } -+ dbNet::destroy(root); -+ Output(name, out); -+ rdata[r].push_back(out); -+ }; -+ if (s.read[r].banked()) { -+ for (int k = 0; k < banks; ++k) { -+ emit(bank_roots[k], Bit(s.read[r].bank_data[k], b)); -+ } -+ } else { -+ dbNet* root -+ = banks == 1 -+ ? bank_roots[0] -+ : OrTree(prefix + "_f", bank_roots, [&](int, int) -> Cursor& { -+ return Least(footer); -+ }); -+ emit(root, Bit(s.read[r].data, b)); -+ } -+ } -+ } -+ for (size_t i = 0; i < tiles_.size(); ++i) { -+ for (const auto& c : tiles_[i].rows) { -+ if (c.x > tiles_[i].x_end) { -+ Refuse( -+ "tile " + std::to_string(i) + " overflowed by " -+ + std::to_string(c.x - tiles_[i].x_end) -+ + " dbu once its read OR trees were in: widen the tile estimate"); -+ } -+ } -+ } -+ for (const auto& c : footer) { -+ if (c.x > core_w) { -+ Refuse("footer overflow: widen the footer estimate"); -+ } -+ } -+ if (max_x_ > core_w) { -+ Refuse("placement ran past the core: " + std::to_string(max_x_) + " > " -+ + std::to_string(core_w)); -+ } -+ -+ // ---- pins on the die edge -------------------------------------------- -+ // Read data along the bottom and write data along the top, on the -+ // vertical layer; addresses, enables and the clock on the left, on the -+ // horizontal layer. Centres sit on the platform's track grid for that -+ // layer so a parent's macro placer can align them (MPL-0005 otherwise). -+ const int track_off = static_cast(s.pin_track_offset_um * dbu_); -+ const int track_pitch -+ = std::max(static_cast(s.pin_track_pitch_um * dbu_), 1); -+ auto on_track = [&](int v) { -+ int k = (v - track_off + track_pitch - 1) / track_pitch; -+ return track_off + std::max(k, 0) * track_pitch; -+ }; -+ const int edge = pin_w_; // pin centre this far in from the die edge -+ int px = on_track(core_x0_ + track_pitch); -+ auto bottom = [&](const std::string& name) { -+ Pin(block_->findBTerm(name.c_str()), layer_v_, px, edge); -+ px += track_pitch; -+ }; -+ for (int r = 0; r < R; ++r) { -+ for (int b = 0; b < s.bits; ++b) { -+ if (s.read[r].banked()) { -+ for (int k = 0; k < banks; ++k) { -+ bottom(Bit(s.read[r].bank_data[k], b)); -+ } -+ } else { -+ bottom(Bit(s.read[r].data, b)); -+ } -+ } -+ } -+ const int px_bottom_end = px; -+ px = on_track(core_x0_ + track_pitch); -+ for (int w = 0; w < W; ++w) { -+ for (int b = 0; b < s.bits; ++b) { -+ Pin(block_->findBTerm(Bit(s.write[w].data, b).c_str()), -+ layer_v_, -+ px, -+ die_h - edge); -+ px += track_pitch; -+ } -+ } -+ int py = on_track(core_y0_ + track_pitch); -+ auto left = [&](const std::string& name) { -+ Pin(block_->findBTerm(name.c_str()), layer_h_, edge, py); -+ py += track_pitch; -+ }; -+ left(s.clock); -+ if (!s.reset.empty()) { -+ left(s.reset); -+ } -+ for (const auto& u : s.unused) { -+ left(u); -+ } -+ for (int r = 0; r < R; ++r) { -+ for (size_t k = 0; k < raddr[r].size(); ++k) { -+ for (size_t i = 0; i < raddr[r][k].size(); ++i) { -+ left(s.read[r].banked() -+ ? Bit(s.read[r].bank_addr[k], static_cast(i)) -+ : Bit(s.read[r].addr, static_cast(i))); -+ } -+ } -+ } -+ for (int w = 0; w < W; ++w) { -+ for (int i = 0; i < A; ++i) { -+ left(Bit(s.write[w].addr, i)); -+ } -+ if (wen[w] != nullptr) { -+ left(s.write[w].en); -+ } -+ } -+ if (std::max(px, px_bottom_end) > die_w || py > die_h) { -+ Refuse( -+ "more pins than the die edge holds at the track pitch; the array " -+ "is too narrow for its ports (widen with fewer banks or more bits)"); -+ } -+ -+ logger_->report( -+ "generate_regfile: {} {}x{} {}R{}W in {} bank(s) as {} x {}, {} bit " -+ "fold(s): " -+ "{} rows of {} sites, die {} x {} um, {} instances", -+ s.module, -+ s.words, -+ s.bits, -+ R, -+ W, -+ banks, -+ bank_cols, -+ bank_rows, -+ folds, -+ total_rows, -+ core_w / site_w_, -+ die_w / static_cast(tech->getLefUnits()), -+ die_h / static_cast(tech->getLefUnits()), -+ block_->getInsts().size()); -+ // In netlist mode the core alone is the generator's: the tiles and the -+ // read bitlines, FIRM. The periphery -- address inverters, read address -+ // registers, each word's decode, hold -- is left unplaced, so the parent's -+ // flow places, sizes and buffers it like any logic: it alone knows the -+ // drivers and loads outside the array. Fixed by the generator, an -+ // address inverter drove its literal into every word's decode at a -+ // 3.7 ns slew on XiangShan's ROB that nothing was allowed to repair. -+ // The abstract is then the core's bounding box and no more: the header -+ // column, the address band and the ring margin are the periphery's or -+ // nobody's, and a parent sizing its floorplan by utilization would -+ // charge them as macro area. -+ // A macro is the generator's to the last cell and keeps its periphery. -+ if (SplitPeriphery(s)) { -+ SplitCore(); -+ } -+ if (s.mode == "netlist") { -+ // The abstract a parent's macro placer sees before the block dissolves -+ // into its rows: each port's pin where its connections land, at the -+ // centroid of the cells on its net -- a write data bit over its -+ // column's write muxes, a read data bit at its bitline's root, an -+ // address among its inverters and decode. Edge pins would tell the -+ // placer's flips nothing about where the wires go; these pins are -+ // never routed, the block dissolves first. -+ std::vector>> moves; -+ for (dbBTerm* t : block_->getBTerms()) { -+ dbNet* net = t->getNet(); -+ if (net == nullptr) { -+ continue; -+ } -+ long long sx = 0, sy = 0; -+ int n = 0; -+ for (odb::dbITerm* it : net->getITerms()) { -+ const odb::Rect b = it->getInst()->getBBox()->getBox(); -+ sx += b.xCenter(); -+ sy += b.yCenter(); -+ ++n; -+ } -+ if (n > 0) { -+ moves.push_back( -+ {t, {static_cast(sx / n), static_cast(sy / n)}}); -+ } -+ } -+ for (dbInst* inst : periphery_insts_) { -+ inst->setPlacementStatus(odb::dbPlacementStatus::UNPLACED); -+ } -+ // The core's bounding box, on the site and row grid as its cells are, -+ // and one row above it becomes the die, its lower left the origin: a -+ // parent whose rows are of the other parity there moves the core up a -+ // row as it dissolves, and the row must be the block's. -+ odb::Rect core; -+ core.mergeInit(); -+ for (dbInst* inst : block_->getInsts()) { -+ if (inst->getPlacementStatus().isPlaced()) { -+ core.merge(inst->getBBox()->getBox()); -+ } -+ } -+ const int dx = core.xMin(); -+ const int dy = core.yMin(); -+ const int first_row = (dy - core_y0_) / row_h_; -+ const int rows = core.dy() / row_h_ + 1; -+ const int box_h = rows * row_h_; -+ for (dbInst* inst : block_->getInsts()) { -+ if (inst->getPlacementStatus().isPlaced()) { -+ const odb::Point at = inst->getLocation(); -+ const odb::dbPlacementStatus status = inst->getPlacementStatus(); -+ // a FIRM cell's origin is fixed (ODB-0359) -+ inst->setPlacementStatus(odb::dbPlacementStatus::PLACED); -+ inst->setLocation(at.x() - dx, at.y() - dy); -+ inst->setPlacementStatus(status); -+ } -+ } -+ std::vector old_rows(block_->getRows().begin(), -+ block_->getRows().end()); -+ for (odb::dbRow* row : old_rows) { -+ odb::dbRow::destroy(row); -+ } -+ for (int r = 0; r < rows; ++r) { -+ std::string rn = "ROW_" + std::to_string(r); -+ odb::dbRow::create(block_, -+ rn.c_str(), -+ site_, -+ 0, -+ r * row_h_, -+ (first_row + r) % 2 == 0 ? odb::dbOrientType::R0 -+ : odb::dbOrientType::MX, -+ odb::dbRowDir::HORIZONTAL, -+ core.dx() / site_w_, -+ site_w_); -+ } -+ block_->setDieArea(odb::Rect(0, 0, core.dx(), box_h)); -+ // Each pin where its connections land, moved with the core and kept -+ // inside it, on the track grid as the edge pins are (MPL-0005 -+ // otherwise). -+ auto inside = [&](int v, int hi) { -+ int t = on_track(std::clamp(v, edge, hi - edge)); -+ while (t > hi - edge && t - track_pitch >= 0) { -+ t -= track_pitch; -+ } -+ return t; -+ }; -+ for (auto& [t, xy] : moves) { -+ std::vector old(t->getBPins().begin(), t->getBPins().end()); -+ for (odb::dbBPin* bp : old) { -+ odb::dbBPin::destroy(bp); -+ } -+ Pin(t, -+ layer_h_, -+ inside(xy.first - dx, core.dx()), -+ inside(xy.second - dy, box_h)); -+ } -+ logger_->report( -+ "generate_regfile: mode netlist, the abstract is the core: {} x {} " -+ "um, {} rows", -+ core.dx() / static_cast(tech->getLefUnits()), -+ box_h / static_cast(tech->getLefUnits()), -+ rows); -+ } -+ if (s.periphery == "verilog") { -+ // synthesis maps the periphery from its assigns; the cells here are -+ // only its description -+ for (dbInst* inst : periphery_insts_) { -+ inst->setPlacementStatus(odb::dbPlacementStatus::UNPLACED); -+ } -+ } -+ return block_; -+} -+ -+} // namespace -+ -+Spec ReadSpec(const std::string& path) -+{ -+ std::ifstream in(path); -+ if (!in) { -+ Refuse("cannot read spec " + path); -+ } -+ Spec s; -+ g_pins = Pins(); -+ std::string line; -+ int lineno = 0; -+ while (std::getline(in, line)) { -+ ++lineno; -+ auto hash = line.find('#'); -+ if (hash != std::string::npos) { -+ line = line.substr(0, hash); -+ } -+ std::istringstream ss(line); -+ std::string key; -+ if (!(ss >> key)) { -+ continue; -+ } -+ std::vector v; -+ for (std::string t; ss >> t;) { -+ v.push_back(t); -+ } -+ auto need = [&](size_t n) { -+ if (v.size() != n) { -+ Refuse(path + ":" + std::to_string(lineno) + ": `" + key + "` takes " -+ + std::to_string(n) + " value(s)"); -+ } -+ }; -+ if (key == "module") { -+ need(1); -+ s.module = v[0]; -+ } else if (key == "mode") { -+ need(1); -+ if (v[0] != "macro" && v[0] != "netlist") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": mode is macro or netlist, not `" + v[0] + "`"); -+ } -+ s.mode = v[0]; -+ } else if (key == "periphery") { -+ need(1); -+ if (v[0] != "generator" && v[0] != "verilog") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": periphery is generator or verilog, not `" + v[0] + "`"); -+ } -+ s.periphery = v[0]; -+ } else if (key == "words") { -+ need(1); -+ s.words = std::stoi(v[0]); -+ } else if (key == "bits") { -+ need(1); -+ s.bits = std::stoi(v[0]); -+ } else if (key == "clock") { -+ need(1); -+ s.clock = v[0]; -+ } else if (key == "reset") { -+ need(1); -+ if (!s.reset.empty()) { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": one of `reset` or `async_reset`, once"); -+ } -+ s.reset = v[0]; -+ } else if (key == "write_priority") { -+ need(1); -+ if (v[0] != "or" && v[0] != "last") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": `write_priority or|last`"); -+ } -+ s.write_priority = v[0]; -+ } else if (key == "unused") { -+ if (v.empty()) { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": `unused ...` names at least one port"); -+ } -+ s.unused.insert(s.unused.end(), v.begin(), v.end()); -+ } else if (key == "async_reset") { -+ need(2); -+ if (!s.reset.empty()) { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": one of `reset` or `async_reset`, once"); -+ } -+ if (v[1] != "low" && v[1] != "high") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": `async_reset low|high`"); -+ } -+ s.reset = v[0]; -+ s.async_reset = true; -+ s.reset_active_low = v[1] == "low"; -+ } else if (key == "read") { -+ need(2); -+ s.read.push_back(Port{.addr = v[0], -+ .data = v[1], -+ .en = "", -+ .bank_addr = {}, -+ .bank_data = {}}); -+ } else if (key == "read_banked") { -+ if (v.size() < 2 || v.size() % 2 != 0) { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": `read_banked` takes addr data pairs, one per bank"); -+ } -+ Port port; -+ for (size_t i = 0; i < v.size(); i += 2) { -+ port.bank_addr.push_back(v[i]); -+ port.bank_data.push_back(v[i + 1]); -+ } -+ s.read.push_back(port); -+ } else if (key == "write") { -+ if (v.size() != 2 && v.size() != 3) { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": `write` takes addr data [en]"); -+ } -+ s.write.push_back(Port{.addr = v[0], -+ .data = v[1], -+ .en = v.size() == 3 ? v[2] : "", -+ .bank_addr = {}, -+ .bank_data = {}}); -+ } else if (key == "cell") { -+ need(2); -+ const std::string& kind = v[0]; -+ if (kind == "flop") { -+ s.cells.flop = v[1]; -+ } else if (kind == "flop_r") { -+ s.cells.flop_r = v[1]; -+ } else if (kind == "tie_hi") { -+ s.cells.tie_hi = v[1]; -+ } else if (kind == "and2") { -+ s.cells.and2 = v[1]; -+ } else if (kind == "or2") { -+ s.cells.or2 = v[1]; -+ } else if (kind == "ao22") { -+ s.cells.ao22 = v[1]; -+ } else if (kind == "aoi22") { -+ s.cells.aoi22 = v[1]; -+ } else if (kind == "nand2") { -+ s.cells.nand2 = v[1]; -+ } else if (kind == "nor2") { -+ s.cells.nor2 = v[1]; -+ } else if (kind == "inv") { -+ s.cells.inv = v[1]; -+ } else if (kind == "tap") { -+ s.cells.tap = v[1]; -+ } else if (kind == "tie_lo") { -+ s.cells.tie_lo = v[1]; -+ } else if (kind == "icg") { -+ s.cells.icg = v[1]; -+ } else { -+ Refuse(path + ":" + std::to_string(lineno) + ": unknown cell kind " -+ + kind); -+ } -+ } else if (key == "pins") { -+ if (v.size() < 2) { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": `pins ...`"); -+ } -+ std::vector pins(v.begin() + 1, v.end()); -+ const std::string& kind = v[0]; -+ auto set = [&](std::vector& dst, size_t n) { -+ if (pins.size() != n) { -+ Refuse(path + ":" + std::to_string(lineno) + ": `pins " + kind -+ + "` takes " + std::to_string(n) + " pin names"); -+ } -+ dst = pins; -+ }; -+ if (kind == "flop") { -+ set(g_pins.flop, 3); -+ } else if (kind == "flop_r") { -+ set(g_pins.flop_r, 5); -+ } else if (kind == "tie_hi") { -+ set(g_pins.tie_hi, 1); -+ } else if (kind == "and2") { -+ set(g_pins.and2, 3); -+ } else if (kind == "or2") { -+ set(g_pins.or2, 3); -+ } else if (kind == "ao22") { -+ set(g_pins.ao22, 5); -+ } else if (kind == "aoi22") { -+ set(g_pins.aoi22, 5); -+ } else if (kind == "nand2") { -+ set(g_pins.nand2, 3); -+ } else if (kind == "nor2") { -+ set(g_pins.nor2, 3); -+ } else if (kind == "inv") { -+ set(g_pins.inv, 2); -+ } else if (kind == "icg") { -+ set(g_pins.icg, 4); -+ } else { -+ Refuse(path + ":" + std::to_string(lineno) + ": unknown pins kind " -+ + kind); -+ } -+ } else if (key == "write_style") { -+ need(1); -+ if (v[0] != "mux" && v[0] != "clock_gate") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": write_style is mux or clock_gate"); -+ } -+ s.write_style = v[0]; -+ } else if (key == "flop_output") { -+ need(1); -+ if (v[0] == "QN") { -+ g_pins.flop_inverted = true; -+ } else if (v[0] == "Q") { -+ g_pins.flop_inverted = false; -+ } else { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": flop_output is Q or QN"); -+ } -+ } else if (key == "pin_layer" || key == "pin_layer_h") { -+ need(1); -+ s.pin_layer_h = v[0]; -+ } else if (key == "pin_layer_v") { -+ need(1); -+ s.pin_layer_v = v[0]; -+ } else if (key == "pin_track") { -+ need(2); -+ s.pin_track_offset_um = std::stod(v[0]); -+ s.pin_track_pitch_um = std::stod(v[1]); -+ } else if (key == "tap_columns") { -+ need(1); -+ s.tap_columns = std::stoi(v[0]); -+ } else if (key == "service_sites") { -+ need(1); -+ s.service_sites = std::stoi(v[0]); -+ } else if (key == "banks") { -+ need(1); -+ s.banks = std::stoi(v[0]); -+ } else if (key == "bank_columns") { -+ need(1); -+ s.bank_columns = std::stoi(v[0]); -+ } else if (key == "bit_folds") { -+ need(1); -+ s.bit_folds = std::stoi(v[0]); -+ } else if (key == "read_latency") { -+ need(1); -+ if (v[0] != "0" && v[0] != "1") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": read_latency is 0 or 1"); -+ } -+ s.read_latency = std::stoi(v[0]); -+ } else if (key == "bank_order") { -+ need(1); -+ if (v[0] != "contiguous" && v[0] != "interleaved") { -+ Refuse(path + ":" + std::to_string(lineno) -+ + ": bank_order is contiguous or interleaved"); -+ } -+ s.bank_order = v[0]; -+ } else if (key == "zero_word") { -+ need(1); -+ s.zero_word = std::stoi(v[0]); -+ } else if (key == "store_name") { -+ need(1); -+ s.store_name = v[0]; -+ } else if (key == "read_reg_name") { -+ need(1); -+ s.read_reg_name = v[0]; -+ } else if (key == "lib") { -+ need(2); -+ double x = std::stod(v[1]); -+ const std::string& knob = v[0]; -+ if (knob == "gate_delay_ps") { -+ s.lib.gate_delay_ps = x; -+ } else if (knob == "wire_factor") { -+ s.lib.wire_factor = x; -+ } else if (knob == "input_load_ff") { -+ s.lib.input_load_ff = x; -+ } else if (knob == "clock_load_ff") { -+ s.lib.clock_load_ff = x; -+ } else if (knob == "leakage_nw_per_cell") { -+ s.lib.leakage_nw_per_cell = x; -+ } else if (knob == "output_max_cap_ff") { -+ s.lib.output_max_cap_ff = x; -+ } else if (knob == "hold_ps") { -+ s.lib.hold_ps = x; -+ } else { -+ Refuse(path + ":" + std::to_string(lineno) + ": unknown lib knob " -+ + knob); -+ } -+ } else { -+ Refuse(path + ":" + std::to_string(lineno) + ": unknown key `" + key -+ + "`"); -+ } -+ } -+ if (s.module.empty()) { -+ Refuse(path + ": no `module`"); -+ } -+ if (s.cells.flop.empty() || s.cells.and2.empty() || s.cells.or2.empty() -+ || s.cells.ao22.empty() || s.cells.inv.empty()) { -+ Refuse(path + ": cells flop, and2, or2, ao22 and inv are all required"); -+ } -+ if (s.async_reset && (s.cells.flop_r.empty() || s.cells.tie_hi.empty())) { -+ Refuse(path + ": `async_reset` needs `cell flop_r` and `cell tie_hi`"); -+ } -+ return s; -+} -+ -+odb::dbBlock* Generate(odb::dbDatabase* db, -+ utl::Logger* logger, -+ const Spec& spec) -+{ -+ Builder b(db, logger, spec); -+ return b.Run(); -+} -+ -+// With `periphery verilog`, each unplaced logic cell of the periphery -+// as an assign of its function: output pin, and the expression over -+// its input pins, `@PIN` standing for the pin's net. -+struct Function -+{ -+ std::string out; -+ std::string expr; -+}; -+ -+static std::map PeripheryFunctions(const Spec& spec) -+{ -+ std::map functions; -+ if (spec.periphery == "verilog") { -+ const Pins& p = g_pins; -+ auto add = [&](const std::string& master, const Function& f) { -+ if (master.empty()) { -+ return; -+ } -+ auto [it, fresh] = functions.emplace(master, f); -+ if (!fresh && it->second.expr != f.expr) { -+ Refuse("cell " + master + " serves two roles with different " -+ "functions; `periphery verilog` needs one per cell"); -+ } -+ }; -+ auto pin = [](const std::string& n) { return "@" + n; }; -+ add(spec.cells.and2, -+ {p.and2[2], pin(p.and2[0]) + " & " + pin(p.and2[1])}); -+ add(spec.cells.or2, {p.or2[2], pin(p.or2[0]) + " | " + pin(p.or2[1])}); -+ add(spec.cells.nand2, -+ {p.nand2[2], "~(" + pin(p.nand2[0]) + " & " + pin(p.nand2[1]) + ")"}); -+ add(spec.cells.nor2, -+ {p.nor2[2], "~(" + pin(p.nor2[0]) + " | " + pin(p.nor2[1]) + ")"}); -+ add(spec.cells.inv, {p.inv[1], "~" + pin(p.inv[0])}); -+ add(spec.cells.ao22, -+ {p.ao22[4], -+ "(" + pin(p.ao22[0]) + " & " + pin(p.ao22[1]) + ") | (" -+ + pin(p.ao22[2]) + " & " + pin(p.ao22[3]) + ")"}); -+ add(spec.cells.aoi22, -+ {p.aoi22[4], -+ "~((" + pin(p.aoi22[0]) + " & " + pin(p.aoi22[1]) + ") | (" -+ + pin(p.aoi22[2]) + " & " + pin(p.aoi22[3]) + "))"}); -+ add(spec.cells.tie_hi, {p.tie_hi[0], "1'b1"}); -+ add(spec.cells.tie_lo, {p.tie_lo[0], "1'b0"}); -+ } -+ return functions; -+} -+ -+// A port net by its port name, buses with [i] intact; any other net -+// escaped. -+static std::string NetRef(odb::dbNet* n) -+{ -+ return n->getBTerms().begin() != n->getBTerms().end() -+ ? n->getName() -+ : "\\" + n->getName() + " "; -+} -+ -+// An assign of `f` for `inst`, its pins by their nets as `net` names them. -+static std::string Assign(const Function& f, -+ const std::string& name, -+ const std::function& net) -+{ -+ std::string expr = f.expr; -+ for (size_t at = expr.find('@'); at != std::string::npos; -+ at = expr.find('@', at)) { -+ size_t end = at + 1; -+ while (end < expr.size() -+ && (std::isalnum(static_cast(expr[end])) -+ || expr[end] == '_')) { -+ ++end; -+ } -+ const std::string r = net(expr.substr(at + 1, end - at - 1)); -+ expr.replace(at, end - at, r.empty() ? "1'b0" : r); -+ at += r.empty() ? 4 : r.size(); -+ } -+ return " assign " + net(f.out) + " = " + expr + "; // " + name + "\n"; -+} -+ -+// The block's ports grouped into buses by `name[i]`, in order. -+struct Bus -+{ -+ odb::dbIoType io; -+ int hi = -1; -+ bool scalar = false; -+}; -+static std::vector> Buses( -+ const std::vector>& ports) -+{ -+ std::map at; -+ std::vector> buses; -+ for (const auto& [n, io] : ports) { -+ auto lb = n.rfind('['); -+ std::string base = n; -+ int idx = -1; -+ if (lb != std::string::npos && n.back() == ']') { -+ base = n.substr(0, lb); -+ idx = std::stoi(n.substr(lb + 1, n.size() - lb - 2)); -+ } -+ auto it = at.find(base); -+ if (it == at.end()) { -+ it = at.emplace(base, buses.size()).first; -+ buses.push_back({base, Bus{io, -1, idx < 0}}); -+ } -+ buses[it->second].second.hi = std::max(buses[it->second].second.hi, idx); -+ } -+ return buses; -+} -+ -+static std::vector> Ports( -+ odb::dbBlock* block) -+{ -+ std::vector> ports; -+ for (odb::dbBTerm* t : block->getBTerms()) { -+ if (t->getSigType() == odb::dbSigType::SIGNAL) { -+ ports.emplace_back(t->getName(), t->getIoType()); -+ } -+ } -+ return ports; -+} -+ -+static void Header(std::ostream& out, -+ const std::string& module, -+ const std::vector>& buses) -+{ -+ out << "module " << module << "(\n"; -+ for (size_t i = 0; i < buses.size(); ++i) { -+ const Bus& b = buses[i].second; -+ out << " " << (b.io == odb::dbIoType::INPUT ? "input" : "output"); -+ if (!b.scalar) { -+ out << " [" << b.hi << ":0]"; -+ } -+ out << " " << buses[i].first << (i + 1 < buses.size() ? ",\n" : "\n"); -+ } -+ out << ");\n"; -+} -+ -+static void WriteStructural(odb::dbBlock* block, -+ const std::string& path, -+ const Spec& spec) -+{ -+ const std::map functions = PeripheryFunctions(spec); -+ std::ofstream out(path); -+ if (!out) { -+ Refuse("cannot write " + path); -+ } -+ out << "// Generated by generate_regfile. Structural" -+ << (functions.empty() ? "" : ", the periphery as assigns") << ".\n"; -+ Header(out, block->getName(), Buses(Ports(block))); -+ for (odb::dbNet* n : block->getNets()) { -+ if (n->getBTerms().begin() != n->getBTerms().end()) { -+ continue; // a port -+ } -+ if (n->getSigType() == odb::dbSigType::POWER -+ || n->getSigType() == odb::dbSigType::GROUND) { -+ continue; -+ } -+ out << " wire \\" << n->getName() << " ;\n"; -+ } -+ for (odb::dbInst* inst : block->getInsts()) { -+ auto f = functions.find(inst->getMaster()->getName()); -+ if (f != functions.end() && !inst->getPlacementStatus().isPlaced()) { -+ odb::dbITerm* y = inst->findITerm(f->second.out.c_str()); -+ if (y == nullptr || y->getNet() == nullptr) { -+ continue; // drives nothing -+ } -+ out << Assign(f->second, inst->getName(), [&](const std::string& pin) { -+ odb::dbITerm* it = inst->findITerm(pin.c_str()); -+ return it != nullptr && it->getNet() != nullptr ? NetRef(it->getNet()) -+ : std::string(); -+ }); -+ continue; -+ } -+ out << " " << inst->getMaster()->getName() << " \\" << inst->getName() -+ << " ("; -+ bool first = true; -+ for (odb::dbITerm* it : inst->getITerms()) { -+ odb::dbNet* n = it->getNet(); -+ if (n == nullptr) { -+ continue; -+ } -+ if (n->getSigType() == odb::dbSigType::POWER -+ || n->getSigType() == odb::dbSigType::GROUND) { -+ continue; -+ } -+ out << (first ? "" : ", ") << "." << it->getMTerm()->getName() << "("; -+ // A port net is written by its port name, buses with [i] intact. -+ out << (n->getBTerms().begin() != n->getBTerms().end() -+ ? n->getName() -+ : "\\" + n->getName() + " ") -+ << ")"; -+ first = false; -+ } -+ out << ");\n"; -+ } -+ out << "endmodule\n"; -+} -+ -+// `periphery verilog` with `mode netlist`: the wrapper module in the RTL -+// module's place, the periphery as assigns and its clock gates as cells -+// around an instance of the core, and the core declared a blackbox for -+// synthesis; the core's netlist goes to .v beside it, for the flow -+// to dissolve. -+static void WriteWrapper(odb::dbBlock* block, -+ const std::string& path, -+ const Spec& spec) -+{ -+ const Wrapper& w = g_wrapper; -+ std::map functions = PeripheryFunctions(spec); -+ std::ofstream out(path); -+ if (!out) { -+ Refuse("cannot write " + path); -+ } -+ out << "// Generated by generate_regfile: the periphery around " -+ << w.core << ".\n"; -+ Header(out, w.module, Buses(w.ports)); -+ for (const auto& n : w.wires) { -+ if (n[0] == '\\') { -+ out << " wire " << n << ";\n"; -+ } -+ } -+ for (const auto& cell : w.cells) { -+ auto f = functions.find(cell.master); -+ auto net = [&](const std::string& pin) { -+ for (const auto& [p, n] : cell.conns) { -+ if (p == pin) { -+ return n; -+ } -+ } -+ return std::string(); -+ }; -+ if (f != functions.end()) { -+ if (!net(f->second.out).empty()) { -+ out << Assign(f->second, cell.name, net); -+ } -+ continue; -+ } -+ out << " " << cell.master << " \\" << cell.name << " ("; -+ for (size_t i = 0; i < cell.conns.size(); ++i) { -+ out << (i ? ", " : "") << "." << cell.conns[i].first << "(" -+ << cell.conns[i].second << ")"; -+ } -+ out << ");\n"; -+ } -+ // The core by its ports: a bus of the module's whole, a shared net bit -+ // by bit. -+ const auto core_buses = Buses(Ports(block)); -+ out << " " << w.core << " core ("; -+ for (size_t i = 0; i < core_buses.size(); ++i) { -+ const std::string& p = core_buses[i].first; -+ std::string n = p; -+ for (const auto& [port, net] : w.core_conns) { -+ if (port == p) { -+ n = net; -+ } -+ } -+ out << (i ? ", " : "") << "." << p << "(" << n << ")"; -+ } -+ out << ");\nendmodule\n\n(* blackbox *)\n"; -+ Header(out, w.core, core_buses); -+ out << "endmodule\n"; -+ const auto slash = path.rfind('/'); -+ const std::string dir -+ = slash == std::string::npos ? "" : path.substr(0, slash + 1); -+ WriteStructural(block, dir + w.core + ".v", spec); -+} -+ -+void WriteVerilog(odb::dbBlock* block, -+ const std::string& path, -+ const Spec& spec) -+{ -+ if (!g_wrapper.core.empty() && block->getName() == g_wrapper.core) { -+ WriteWrapper(block, path, spec); -+ } else { -+ WriteStructural(block, path, spec); -+ } -+} -+ -+} // namespace ram::regfile -diff --git a/src/ram/src/regfile.h b/src/ram/src/regfile.h -new file mode 100644 -index 00000000000..649ac3fe814 ---- /dev/null -+++ b/src/ram/src/regfile.h -@@ -0,0 +1,194 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+// Copyright (c) 2026, The OpenROAD Authors -+ -+// generate_regfile: a multi-port register file as a placed standard-cell -+// macro, built directly in odb. -+// -+// A register file synthesised to flops is a flop per bit, a W-way write -+// mux on each flop's D and an R-way read mux tree per bit: dense, and the -+// legaliser cannot spread it. Here it is laid out the way a bitcell array -+// is: word rows by bit columns, one tile per (word, bit) holding the flop, -+// its write select and R read AND gates; the read wordlines run along the -+// rows and are decoded in a header column, the read bitlines are OR trees -+// in a footer row. Every cell is placed by construction; nothing is left -+// to a placer. -+#pragma once -+ -+#include -+#include -+ -+namespace odb { -+class dbDatabase; -+class dbBlock; -+class dbMaster; -+class dbNet; -+class dbInst; -+} // namespace odb -+ -+namespace utl { -+class Logger; -+} -+ -+namespace ram::regfile { -+ -+// One read or write port, with the RTL's own pin names so the macro drops -+// in for the module it replaces. -+struct Port -+{ -+ std::string addr; // bus name; bits are [i] -+ std::string data; // bus name; bits are [i] -+ std::string en; // write ports only; empty means always enabled -+ // A banked read port (Chisel RegfileBank): one address and one data bus -+ // per bank, the bank mux outside. addr/data above are unused then. -+ std::vector bank_addr; -+ std::vector bank_data; -+ bool banked() const { return !bank_addr.empty(); } -+}; -+ -+// The cells the array is built from, by name in the loaded LEF. -+struct Cells -+{ -+ std::string flop; // D flip-flop, Q output (QN accepted, see below) -+ // the storage flop with `async_reset`: an asynchronous reset (RESETN) -+ // and set (SETN, tied off) flop -+ std::string flop_r; -+ std::string tie_hi; // ties flop_r's set off, one per word -+ std::string and2; // read select AND -+ std::string or2; // bitline OR tree node -+ std::string ao22; // write mux node: (sel & new) | (hold & old) -+ // read bitline: AOI22 leaf per word pair, NAND2/NOR2 tree over them -+ std::string aoi22 = "AOI22xp5_ASAP7_75t_R"; -+ std::string nand2 = "NAND2xp5_ASAP7_75t_R"; -+ std::string nor2 = "NOR2xp33_ASAP7_75t_R"; -+ std::string inv; // decoder inverters -+ std::string tap; // well tap, one column per tap_columns -+ // integrated clock gate, one per word with `write_style clock_gate` -+ std::string icg = "ICGx1_ASAP7_75t_R"; -+ std::string tie_lo; // for unused inputs -+}; -+ -+// Knobs of the model liberty (views.h), asap7-shaped defaults, set in -+// the spec with `lib `. Picoseconds, femtofarads, -+// nanowatts, so a spec reads in plain units. -+struct LibModel -+{ -+ double gate_delay_ps = 25.0; // one loaded gate level -+ double wire_factor = 1.3; // on top of the gate levels -+ double input_load_ff = 0.6; // per driven cell input -+ double clock_load_ff = 10.0; // the block's clock pin as the parent sees it -+ double leakage_nw_per_cell = 1.0; -+ double output_max_cap_ff = 50.0; -+ double hold_ps = 0.0; -+}; -+ -+struct Spec -+{ -+ // "macro" (an abstract and a model liberty for a parent to place) or -+ // "netlist" (the placed cells dropped into the parent's rows by the -+ // flow); the generator builds the same block either way. The flow's -+ // memories step reads this key too, and decides which views to ask for. -+ std::string mode = "macro"; -+ // Who builds the periphery -- address inverters, decode, write muxes, -+ // hold: "generator" (cells, placed with the array or, in mode netlist, -+ // left unplaced for the parent) or "verilog" (written as assigns of -+ // the cells' functions, for synthesis to map with the parent's logic; -+ // the clock gates stay cells). Neither dominates: it depends on how -+ // the array is integrated. -+ std::string periphery = "generator"; -+ std::string module; // generated module and block name -+ int words = 0; -+ int bits = 0; -+ std::string clock = "clock"; -+ std::string reset; // optional: a port the RTL has and the array ignores -+ // `async_reset low|high`: the reset clears every stored word to -+ // zero asynchronously, as an RTL `always @(posedge clk or negedge -+ // rst_n)` register file does; the storage flops are `cell flop_r`. The -+ // port is `reset` above. Read-address registers (read_latency) are not -+ // reset. -+ bool async_reset = false; -+ bool reset_active_low = true; -+ // `unused `: one-bit inputs the RTL module has and the array -+ // ignores (ibex's test_en_i), so the block has the module's ports. -+ std::vector unused; -+ std::vector read; -+ std::vector write; -+ Cells cells; -+ int tap_columns = 8; // a tap column every N bit columns -+ // free sites beside each tap, for the clock tree; -1: 40 in a macro, -+ // none in netlist mode -+ int service_sites = -1; -+ int banks = 1; // word columns side by side; words % banks == 0 -+ // How many of the banks stand side by side; the rest stack below them. -+ // 0 means all of them, one row of banks. The outline is bank_columns -+ // bank widths wide and banks/bank_columns bank heights tall: a wide -+ // word (128 bits) wants its banks stacked, a narrow one wants them -+ // side by side. banks % bank_columns == 0. -+ int bank_columns = 0; -+ // The word split into this many bit bands, stacked: a 564-bit word -+ // is one band 564 tiles wide, or four bands of 141 one above the -+ // other, each with its own copy of the word decode; the last band is -+ // short when the folds do not divide. Banks fold words; this folds bits. -+ int bit_folds = 1; -+ // Read latency in cycles: 0 reads combinationally from the address -+ // ports; 1 registers each read address on the clock first, the way -+ // firtool writes a Chisel register file read through RegNext(addr) -+ // (XiangShan's IntRegFile, FpRegFile and VfRegFile). The macro -+ // replaces the whole module, so it has to carry that register. -+ int read_latency = 0; -+ // How words fall into banks: "contiguous" (bank n / words_per_bank, -+ // the default) or "interleaved" (bank n % banks, entry n / banks, as -+ // XiangShan's IntRegFile banks its read: bank k's entry l is word -+ // l * banks + k). -+ std::string bank_order = "contiguous"; -+ // A word that is the constant zero and has no storage (RISC-V x0): it -+ // reads 0 and a write to it is dropped. -1 for none. -+ int zero_word = -1; -+ // How a word keeps its value between writes: "mux" (the default), a -+ // free-running clock and a hold term in every bit's write mux; or -+ // "clock_gate", one integrated clock gate per word enabled by any of -+ // its write selects, as generate_ram writes, so a bit's D is the write -+ // data itself with one write port and a select mux of the writes with -+ // more. -+ std::string write_style = "mux"; -+ // Two ports writing one word in one cycle: "or" (the default) ORs their -+ // data, for an RTL that never does it; "last", the later port in the -+ // spec wins, as an RTL's later assignment does (cva6's commit ports). -+ std::string write_priority = "or"; -+ // Instance names of the flops, as patterns, so a flop carries the name -+ // of the RTL register bit it implements (an equivalence check matches -+ // sequential instances by name). {word} {bit} for the storage, -+ // {port} {bank} {bit} for a read address register. Empty keeps the -+ // generator's own names. -+ std::string store_name; -+ std::string read_reg_name; -+ LibModel lib; -+ // Pins: left and right edges on the horizontal layer, top and bottom on -+ // the vertical one, centred on that layer's track grid as the platform -+ // makes it, so a parent's macro placer can align them. -+ std::string pin_layer_h = "M4"; -+ std::string pin_layer_v = "M5"; -+ double pin_track_offset_um = 0.012; -+ double pin_track_pitch_um = 0.048; -+}; -+ -+// Reads a spec from a small `key value` text file (see README.md). -+// Throws std::runtime_error with the offending line on anything it does -+// not understand: a spec is either complete or refused. -+Spec ReadSpec(const std::string& path); -+ -+// Builds the netlist and placement of `spec` into a new block of `db`, -+// whose tech and libs must already hold the cells named in the spec. -+// Returns the block. Throws std::runtime_error naming the cell or pin -+// when the library does not fit the spec. -+odb::dbBlock* Generate(odb::dbDatabase* db, -+ utl::Logger* logger, -+ const Spec& spec); -+ -+// Writes the block as a structural Verilog module, cells as instances, -+// for simulation and for the flow's netlist view; with `periphery -+// verilog`, the unplaced periphery's logic cells as assigns. -+void WriteVerilog(odb::dbBlock* block, -+ const std::string& path, -+ const Spec& spec); -+ -+} // namespace ram::regfile -diff --git a/src/ram/src/regfile_cmd.cpp b/src/ram/src/regfile_cmd.cpp -new file mode 100644 -index 00000000000..d90332ba559 ---- /dev/null -+++ b/src/ram/src/regfile_cmd.cpp -@@ -0,0 +1,93 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+// Copyright (c) 2026, The OpenROAD Authors -+ -+#include -+#include -+#include -+ -+#include "odb/db.h" -+#include "odb/defout.h" -+#include "ram/regfile.h" -+#include "regfile.h" -+#include "utl/Logger.h" -+#include "views.h" -+ -+namespace ram { -+ -+void generateRegfile(odb::dbDatabase* db, -+ utl::Logger* logger, -+ const std::string& spec_path, -+ const std::string& verilog_path, -+ const std::string& def_path, -+ const std::string& lef_path, -+ const std::string& liberty_path, -+ const std::string& check_ports) -+{ -+ try { -+ regfile::Spec spec = regfile::ReadSpec(spec_path); -+ if (!check_ports.empty()) { -+ // The spec against the RTL it stands in for, before anything is -+ // built: a block whose ports are not the module's is a silent -+ // miswire at the parent. -+ auto ports = regfile::ReadModulePorts(check_ports, spec.module); -+ auto problems = regfile::CheckPorts(spec, ports); -+ if (!problems.empty()) { -+ std::string all; -+ for (const auto& p : problems) { -+ all += "\n " + p; -+ } -+ throw std::runtime_error("spec does not match module " + spec.module -+ + " in " + check_ports + ":" + all); -+ } -+ } -+ odb::dbBlock* block = regfile::Generate(db, logger, spec); -+ // In mode netlist the generator fixes the core and leaves the -+ // periphery to the parent, which alone knows the drivers and loads -+ // outside the array; the block on its own shows those cells unplaced. -+ int fixed = 0; -+ int unplaced = 0; -+ for (odb::dbInst* inst : block->getInsts()) { -+ if (!inst->getPlacementStatus().isPlaced()) { -+ ++unplaced; -+ } else if (inst->getPlacementStatus().isFixed()) { -+ ++fixed; -+ } -+ } -+ if (unplaced > 0) { -+ logger->info(utl::RAM, -+ 52, -+ "mode {}: {} periphery instances left unplaced for the " -+ "parent to place, size and buffer; {} fixed.", -+ spec.mode, -+ unplaced, -+ fixed); -+ } -+ if (!verilog_path.empty()) { -+ regfile::WriteVerilog(block, verilog_path, spec); -+ } -+ if (!def_path.empty()) { -+ odb::DefOut writer(logger); -+ if (!writer.writeBlock(block, def_path.c_str())) { -+ throw std::runtime_error("cannot write " + def_path); -+ } -+ } -+ if (!lef_path.empty()) { -+ regfile::WriteLef(block, logger, lef_path); -+ } -+ if (!liberty_path.empty()) { -+ // A flow's memories directory holds .lib and _pre_layout.lib; -+ // the model is the same file twice, said so in its comment. -+ regfile::WriteLiberty(block, spec, spec.lib, liberty_path, false); -+ std::string pre = liberty_path; -+ auto dot = pre.rfind(".lib"); -+ if (dot != std::string::npos) { -+ pre = pre.substr(0, dot) + "_pre_layout.lib"; -+ regfile::WriteLiberty(block, spec, spec.lib, pre, true); -+ } -+ } -+ } catch (const std::exception& e) { -+ logger->error(utl::RAM, 50, "generate_regfile: {}", e.what()); -+ } -+} -+ -+} // namespace ram -diff --git a/src/ram/src/views.cpp b/src/ram/src/views.cpp -new file mode 100644 -index 00000000000..1fe0e3bba55 ---- /dev/null -+++ b/src/ram/src/views.cpp -@@ -0,0 +1,752 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+// Copyright (c) 2026, The OpenROAD Authors -+ -+// generate_regfile: abstract LEF, model liberty, and the spec-against-RTL -+// port check. See views.h. -+#include "views.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "odb/db.h" -+#include "odb/lefout.h" -+#include "regfile.h" -+#include "utl/Logger.h" -+ -+namespace ram::regfile { -+ -+namespace { -+ -+int Log2Ceil(int n) -+{ -+ int k = 0; -+ while ((1 << k) < n) { -+ ++k; -+ } -+ return k; -+} -+ -+int AddrWidth(int words) -+{ -+ return std::max(Log2Ceil(words), 1); -+} -+ -+// An integer constant expression of a module header: decimal numbers, -+// parameters by name, + - * / and parentheses. Throws naming what it -+// cannot evaluate: a width the check cannot read is a refusal, not a -+// port to skip. -+class ConstExpr -+{ -+ public: -+ ConstExpr(const std::string& text, const std::map& params) -+ : text_(text), params_(params) -+ { -+ } -+ long Eval() -+ { -+ long v = Sum(); -+ Space(); -+ if (pos_ != text_.size()) { -+ Fail(); -+ } -+ return v; -+ } -+ -+ private: -+ void Space() -+ { -+ while (pos_ < text_.size() -+ && std::isspace(static_cast(text_[pos_]))) { -+ ++pos_; -+ } -+ } -+ [[noreturn]] void Fail() -+ { -+ throw std::runtime_error("cannot evaluate `" + text_ -+ + "` in a module header"); -+ } -+ long Sum() -+ { -+ long v = Product(); -+ for (;;) { -+ Space(); -+ if (pos_ < text_.size() && (text_[pos_] == '+' || text_[pos_] == '-')) { -+ const char op = text_[pos_++]; -+ const long r = Product(); -+ v = op == '+' ? v + r : v - r; -+ } else { -+ return v; -+ } -+ } -+ } -+ long Product() -+ { -+ long v = Atom(); -+ for (;;) { -+ Space(); -+ if (pos_ < text_.size() && (text_[pos_] == '*' || text_[pos_] == '/')) { -+ const char op = text_[pos_++]; -+ const long r = Atom(); -+ if (op == '/' && r == 0) { -+ Fail(); -+ } -+ v = op == '*' ? v * r : v / r; -+ } else { -+ return v; -+ } -+ } -+ } -+ long Atom() -+ { -+ Space(); -+ if (pos_ >= text_.size()) { -+ Fail(); -+ } -+ if (text_[pos_] == '(') { -+ ++pos_; -+ const long v = Sum(); -+ Space(); -+ if (pos_ >= text_.size() || text_[pos_] != ')') { -+ Fail(); -+ } -+ ++pos_; -+ return v; -+ } -+ if (text_[pos_] == '-') { -+ ++pos_; -+ return -Atom(); -+ } -+ if (std::isdigit(static_cast(text_[pos_]))) { -+ long v = 0; -+ while (pos_ < text_.size() -+ && std::isdigit(static_cast(text_[pos_]))) { -+ v = v * 10 + (text_[pos_++] - '0'); -+ } -+ return v; -+ } -+ size_t start = pos_; -+ while (pos_ < text_.size() -+ && (std::isalnum(static_cast(text_[pos_])) -+ || text_[pos_] == '_')) { -+ ++pos_; -+ } -+ auto it = params_.find(text_.substr(start, pos_ - start)); -+ if (start == pos_ || it == params_.end()) { -+ Fail(); -+ } -+ return it->second; -+ } -+ std::string text_; -+ const std::map& params_; -+ size_t pos_ = 0; -+}; -+ -+// `text` without its // and /* */ comments. -+std::string StripComments(const std::string& text) -+{ -+ std::string out; -+ out.reserve(text.size()); -+ for (size_t i = 0; i < text.size(); ++i) { -+ if (text.compare(i, 2, "//") == 0) { -+ i = text.find('\n', i); -+ if (i == std::string::npos) { -+ break; -+ } -+ out += '\n'; -+ } else if (text.compare(i, 2, "/*") == 0) { -+ i = text.find("*/", i + 2); -+ if (i == std::string::npos) { -+ break; -+ } -+ ++i; -+ } else { -+ out += text[i]; -+ } -+ } -+ return out; -+} -+ -+// The text between the parenthesis at `open` and its match. -+std::string Balanced(const std::string& text, size_t open, size_t* end) -+{ -+ int depth = 0; -+ for (size_t i = open; i < text.size(); ++i) { -+ if (text[i] == '(') { -+ ++depth; -+ } else if (text[i] == ')' && --depth == 0) { -+ *end = i; -+ return text.substr(open + 1, i - open - 1); -+ } -+ } -+ throw std::runtime_error("unbalanced parentheses in a module header"); -+} -+ -+// Splits at the commas outside brackets and parentheses. -+std::vector TopLevelCommas(const std::string& text) -+{ -+ std::vector out; -+ int depth = 0; -+ std::string cur; -+ for (char c : text) { -+ if (c == '(' || c == '[' || c == '{') { -+ ++depth; -+ } else if (c == ')' || c == ']' || c == '}') { -+ --depth; -+ } -+ if (c == ',' && depth == 0) { -+ out.push_back(cur); -+ cur.clear(); -+ } else { -+ cur += c; -+ } -+ } -+ out.push_back(cur); -+ return out; -+} -+ -+std::string F(double v) -+{ -+ std::ostringstream s; -+ s.precision(6); -+ s << std::fixed << v; -+ return s.str(); -+} -+ -+// The two-point tables FakeRAM's libs use: constant across slew and load, -+// which is what a model is. -+void Table2(std::ostream& o, -+ const char* kind, -+ const std::string& tmpl, -+ double value_ns, -+ int indent) -+{ -+ std::string pad(indent, ' '); -+ o << pad << kind << "(" << tmpl << ") {\n" -+ << pad << " index_1 (\"0.009, 0.227\");\n" -+ << pad << " index_2 (\"0.005, 0.500\");\n" -+ << pad << " values ( \\\n" -+ << pad << " \"" << F(value_ns) << ", " << F(value_ns) << "\", \\\n" -+ << pad << " \"" << F(value_ns) << ", " << F(value_ns) << "\" \\\n" -+ << pad << " )\n" -+ << pad << "}\n"; -+} -+ -+void Constraint(std::ostream& o, -+ const std::string& cell, -+ const std::string& clk, -+ double setup_ns, -+ double hold_ns) -+{ -+ o << " timing() {\n" -+ << " related_pin : " << clk << ";\n" -+ << " timing_type : setup_rising ;\n"; -+ Table2(o, "rise_constraint", cell + "_constraint_template", setup_ns, 12); -+ Table2(o, "fall_constraint", cell + "_constraint_template", setup_ns, 12); -+ o << " }\n" -+ << " timing() {\n" -+ << " related_pin : " << clk << ";\n" -+ << " timing_type : hold_rising ;\n"; -+ Table2(o, "rise_constraint", cell + "_constraint_template", hold_ns, 12); -+ Table2(o, "fall_constraint", cell + "_constraint_template", hold_ns, 12); -+ o << " }\n"; -+} -+ -+} // namespace -+ -+void WriteLef(odb::dbBlock* block, utl::Logger* logger, const std::string& path) -+{ -+ std::ofstream out(path); -+ if (!out) { -+ throw std::runtime_error("cannot write " + path); -+ } -+ odb::lefout writer(logger, out); -+ writer.setBloatOccupiedLayers(true); -+ writer.writeAbstractLef(block); -+} -+ -+// The core of `periphery verilog` in `mode netlist`, _core: a -+// blackbox to synthesis and a macro to macro placement until it -+// dissolves, so its area and its pins, and no arcs; its ports are the -+// nets it shares with the periphery, which the spec's model knows -+// nothing of. -+static void WriteCoreLiberty(odb::dbBlock* block, const std::string& path) -+{ -+ std::ofstream o(path); -+ if (!o) { -+ throw std::runtime_error("cannot write " + path); -+ } -+ const std::string cell = block->getName(); -+ const odb::Rect die = block->getDieArea(); -+ const double dbu = block->getDbUnitsPerMicron(); -+ struct Bus -+ { -+ bool input = true; -+ int hi = -1; -+ }; -+ std::map buses; -+ std::vector order; -+ for (odb::dbBTerm* t : block->getBTerms()) { -+ if (t->getSigType() != odb::dbSigType::SIGNAL) { -+ continue; -+ } -+ std::string n = t->getName(); -+ int idx = -1; -+ const auto lb = n.rfind('['); -+ if (lb != std::string::npos && n.back() == ']') { -+ idx = std::stoi(n.substr(lb + 1, n.size() - lb - 2)); -+ n = n.substr(0, lb); -+ } -+ if (buses.find(n) == buses.end()) { -+ order.push_back(n); -+ buses[n].input = t->getIoType() == odb::dbIoType::INPUT; -+ } -+ buses[n].hi = std::max(buses[n].hi, idx); -+ } -+ o << "library(" << cell << ") {\n" -+ << " comment : \"generate_regfile: the core of a periphery verilog " -+ "register file, area and pins only\";\n" -+ << " delay_model : table_lookup;\n" -+ << " time_unit : \"1ns\";\n" -+ << " voltage_unit : \"1V\";\n" -+ << " current_unit : \"1uA\";\n" -+ << " leakage_power_unit : \"1uW\";\n" -+ << " capacitive_load_unit (1,pf);\n" -+ << " pulling_resistance_unit : \"1kohm\";\n" -+ << " nom_process : 1;\n" -+ << " nom_temperature : 25.000;\n" -+ << " nom_voltage : 0.700;\n"; -+ std::set widths; -+ for (const auto& [n, b] : buses) { -+ if (b.hi >= 0) { -+ widths.insert(b.hi + 1); -+ } -+ } -+ for (int w : widths) { -+ o << " type (" << cell << "_bus_" << w << ") {\n" -+ << " base_type : array ;\n" -+ << " data_type : bit ;\n" -+ << " bit_width : " << w << ";\n" -+ << " bit_from : " << w - 1 << ";\n" -+ << " bit_to : 0 ;\n" -+ << " downto : true ;\n" -+ << " }\n"; -+ } -+ o << "cell(" << cell << ") {\n" -+ << " area : " << F(die.dx() / dbu * (die.dy() / dbu)) << ";\n" -+ << " is_macro_cell : true;\n" -+ << " dont_touch : true;\n"; -+ for (const auto& n : order) { -+ const Bus& b = buses[n]; -+ const char* dir = b.input ? "input" : "output"; -+ if (b.hi < 0) { -+ o << " pin(" << n << ") {\n direction : " << dir -+ << ";\n capacitance : 0.001;\n }\n"; -+ } else { -+ o << " bus(" << n << ") {\n bus_type : " << cell << "_bus_" -+ << b.hi + 1 << ";\n direction : " << dir -+ << ";\n capacitance : 0.001;\n }\n"; -+ } -+ } -+ o << "}\n}\n"; -+} -+ -+void WriteLiberty(odb::dbBlock* block, -+ const Spec& spec, -+ const LibModel& m, -+ const std::string& path, -+ bool pre_layout) -+{ -+ std::ofstream o(path); -+ if (!o) { -+ throw std::runtime_error("cannot write " + path); -+ } -+ if (block->getName() != spec.module) { -+ WriteCoreLiberty(block, path); -+ return; -+ } -+ const std::string cell = spec.module; -+ const int A = AddrWidth(spec.words); -+ const int R = static_cast(spec.read.size()); -+ const int W = static_cast(spec.write.size()); -+ const int banks = std::max(spec.banks, 1); -+ const int words_per_bank = spec.words / banks; -+ -+ // Gate levels, from the structure the generator built (regfile.cc). -+ const int read_levels -+ = 1 + Log2Ceil(A) + 1 + Log2Ceil(words_per_bank) + Log2Ceil(banks); -+ const int write_levels = 1 + Log2Ceil(A + 1) + 1 + Log2Ceil((W + 2) / 2); -+ const double read_ns = read_levels * m.gate_delay_ps * m.wire_factor / 1000.0; -+ const double setup_ns -+ = write_levels * m.gate_delay_ps * m.wire_factor / 1000.0; -+ const double hold_ns = m.hold_ps / 1000.0; -+ // Loads, from fanout: an address literal reaches one inverter and half -+ // the words' decodes; a data bit reaches every word's write mux; an -+ // enable reaches every word's decode. -+ const double addr_pf = (spec.words / 2 + 1) * m.input_load_ff / 1000.0; -+ const double data_pf = spec.words * m.input_load_ff / 1000.0; -+ const double en_pf = spec.words * m.input_load_ff / 1000.0; -+ const double clk_pf = m.clock_load_ff / 1000.0; -+ const odb::Rect die = block->getDieArea(); -+ const double dbu = block->getDbUnitsPerMicron(); -+ const double area_um2 = die.dx() / dbu * (die.dy() / dbu); -+ const double leakage_uw -+ = block->getInsts().size() * m.leakage_nw_per_cell / 1000.0; -+ -+ o << "library(" << cell << ") {\n" -+ << " technology (cmos);\n" -+ << " delay_model : table_lookup;\n" -+ << " revision : 1.0;\n" -+ << " comment : \"generate_regfile model" -+ << (pre_layout ? ", pre-layout" : "") -+ << ": loads from fanout, arcs from gate depth; replaced by the routed " -+ "block's abstract for a measured run\";\n" -+ << " time_unit : \"1ns\";\n" -+ << " voltage_unit : \"1V\";\n" -+ << " current_unit : \"1uA\";\n" -+ << " leakage_power_unit : \"1uW\";\n" -+ << " nom_process : 1;\n" -+ << " nom_temperature : 25.000;\n" -+ << " nom_voltage : 0.700;\n" -+ << " capacitive_load_unit (1,pf);\n" -+ << " pulling_resistance_unit : \"1kohm\";\n" -+ << " operating_conditions(tt_1.0_25.0) {\n" -+ << " process : 1;\n" -+ << " temperature : 25.000;\n" -+ << " voltage : 0.700;\n" -+ << " tree_type : balanced_tree;\n" -+ << " }\n" -+ << " default_cell_leakage_power : 0;\n" -+ << " default_fanout_load : 1;\n" -+ << " default_inout_pin_cap : 0.0;\n" -+ << " default_input_pin_cap : 0.0;\n" -+ << " default_output_pin_cap : 0.0;\n" -+ << " default_max_transition : 0.227;\n" -+ << " default_operating_conditions : tt_1.0_25.0;\n" -+ << " default_leakage_power_density : 0.0;\n" -+ << " slew_derate_from_library : 1.000;\n" -+ << " slew_lower_threshold_pct_fall : 20.000;\n" -+ << " slew_upper_threshold_pct_fall : 80.000;\n" -+ << " slew_lower_threshold_pct_rise : 20.000;\n" -+ << " slew_upper_threshold_pct_rise : 80.000;\n" -+ << " input_threshold_pct_fall : 50.000;\n" -+ << " input_threshold_pct_rise : 50.000;\n" -+ << " output_threshold_pct_fall : 50.000;\n" -+ << " output_threshold_pct_rise : 50.000;\n" -+ << " lu_table_template(" << cell << "_delay_template) {\n" -+ << " variable_1 : input_net_transition;\n" -+ << " variable_2 : total_output_net_capacitance;\n" -+ << " index_1 (\"1000, 1001\");\n" -+ << " index_2 (\"1000, 1001\");\n" -+ << " }\n" -+ << " lu_table_template(" << cell << "_slew_template) {\n" -+ << " variable_1 : total_output_net_capacitance;\n" -+ << " index_1 (\"1000, 1001\");\n" -+ << " }\n" -+ << " lu_table_template(" << cell << "_constraint_template) {\n" -+ << " variable_1 : related_pin_transition;\n" -+ << " variable_2 : constrained_pin_transition;\n" -+ << " index_1 (\"1000, 1001\");\n" -+ << " index_2 (\"1000, 1001\");\n" -+ << " }\n" -+ << " library_features(report_delay_calculation);\n"; -+ const int A_bank = AddrWidth(words_per_bank); -+ // One bus type per width in use. -+ std::set widths = {A, spec.bits, A_bank}; -+ for (int w : widths) { -+ o << " type (" << cell << "_bus_" << w << ") {\n" -+ << " base_type : array ;\n" -+ << " data_type : bit ;\n" -+ << " bit_width : " << w << ";\n" -+ << " bit_from : " << w - 1 << ";\n" -+ << " bit_to : 0 ;\n" -+ << " downto : true ;\n" -+ << " }\n"; -+ } -+ o << "cell(" << cell << ") {\n" -+ << " area : " << F(area_um2) << ";\n" -+ << " is_macro_cell : true;\n" -+ << " interface_timing : true;\n"; -+ // Clock. -+ o << " pin(" << spec.clock << ") {\n" -+ << " direction : input;\n" -+ << " capacitance : " << F(clk_pf) << ";\n" -+ << " clock : true;\n" -+ << " }\n"; -+ std::vector quiet = spec.unused; -+ if (!spec.reset.empty()) { -+ quiet.insert(quiet.begin(), spec.reset); -+ } -+ for (const auto& name : quiet) { -+ o << " pin(" << name << ") {\n" -+ << " direction : input;\n" -+ << " capacitance : 0.001000;\n" -+ << " }\n"; -+ } -+ // Read ports: address in, data out combinational from that address; with -+ // a read latency the address is a flop's D (setup and hold to the clock) -+ // and the data comes from the clock, one flop level more. A banked port -+ // is one such pair per bank, with the bank-local width. -+ const bool registered = spec.read_latency > 0; -+ const double flop_ns = m.gate_delay_ps * m.wire_factor / 1000.0; -+ auto read_pair = [&](const std::string& addr, -+ const std::string& data, -+ int a_width, -+ double read_ns_here) { -+ o << " bus(" << addr << ") {\n" -+ << " bus_type : " << cell << "_bus_" << a_width << ";\n" -+ << " direction : input;\n" -+ << " capacitance : " -+ << F(registered ? m.input_load_ff / 1000.0 : addr_pf) << ";\n"; -+ if (registered) { -+ Constraint(o, cell, spec.clock, flop_ns, hold_ns); -+ } -+ o << " }\n" -+ << " bus(" << data << ") {\n" -+ << " bus_type : " << cell << "_bus_" << spec.bits << ";\n" -+ << " direction : output;\n" -+ << " max_capacitance : " << F(m.output_max_cap_ff / 1000.0) -+ << ";\n"; -+ // The arc per data bit, related to every address bit: a bus-to-bus -+ // arc between an A-bit address and a B-bit data would be read as -+ // bitwise pairs of different sizes (STA-1216). Every data bit -+ // depends on every address bit here. -+ std::string addr_bits; -+ for (int i = 0; i < a_width; ++i) { -+ addr_bits += (i ? " " : "") + addr + "[" + std::to_string(i) + "]"; -+ } -+ for (int b = 0; b < spec.bits; ++b) { -+ o << " pin(" << data << "[" << b << "]) {\n" -+ << " direction : output;\n" -+ << " timing() {\n"; -+ if (registered) { -+ o << " related_pin : " << spec.clock << " ;\n" -+ << " timing_type : rising_edge;\n"; -+ } else { -+ o << " related_pin : \"" << addr_bits << "\" ;\n" -+ << " timing_type : combinational;\n" -+ << " timing_sense : non_unate;\n"; -+ } -+ const double arc_ns = read_ns_here + (registered ? flop_ns : 0.0); -+ Table2(o, "cell_rise", cell + "_delay_template", arc_ns, 16); -+ Table2(o, "cell_fall", cell + "_delay_template", arc_ns, 16); -+ o << " rise_transition(" << cell << "_slew_template) {\n" -+ << " index_1 (\"0.005, 0.500\");\n" -+ << " values (\"0.009, 0.227\")\n" -+ << " }\n" -+ << " fall_transition(" << cell << "_slew_template) {\n" -+ << " index_1 (\"0.005, 0.500\");\n" -+ << " values (\"0.009, 0.227\")\n" -+ << " }\n" -+ << " }\n" -+ << " }\n"; -+ } -+ o << " }\n"; -+ }; -+ // A banked port's read has no footer level. -+ const int bank_read_levels -+ = 1 + Log2Ceil(A_bank) + 1 + Log2Ceil(words_per_bank); -+ const double bank_read_ns -+ = bank_read_levels * m.gate_delay_ps * m.wire_factor / 1000.0; -+ for (int r = 0; r < R; ++r) { -+ if (spec.read[r].banked()) { -+ for (size_t k = 0; k < spec.read[r].bank_addr.size(); ++k) { -+ read_pair(spec.read[r].bank_addr[k], -+ spec.read[r].bank_data[k], -+ A_bank, -+ bank_read_ns); -+ } -+ } else { -+ read_pair(spec.read[r].addr, spec.read[r].data, A, read_ns); -+ } -+ } -+ // Write ports: everything constrained to the clock. -+ for (int w = 0; w < W; ++w) { -+ o << " bus(" << spec.write[w].addr << ") {\n" -+ << " bus_type : " << cell << "_bus_" << A << ";\n" -+ << " direction : input;\n" -+ << " capacitance : " << F(addr_pf) << ";\n"; -+ Constraint(o, cell, spec.clock, setup_ns, hold_ns); -+ o << " }\n" -+ << " bus(" << spec.write[w].data << ") {\n" -+ << " bus_type : " << cell << "_bus_" << spec.bits << ";\n" -+ << " direction : input;\n" -+ << " capacitance : " << F(data_pf) << ";\n"; -+ Constraint(o, cell, spec.clock, setup_ns, hold_ns); -+ o << " }\n"; -+ if (!spec.write[w].en.empty()) { -+ o << " pin(" << spec.write[w].en << ") {\n" -+ << " direction : input;\n" -+ << " capacitance : " << F(en_pf) << ";\n"; -+ Constraint(o, cell, spec.clock, setup_ns, hold_ns); -+ o << " }\n"; -+ } -+ } -+ o << " cell_leakage_power : " << F(leakage_uw) << ";\n" -+ << "}\n" -+ << "}\n"; -+} -+ -+std::vector ReadModulePorts(const std::string& verilog, -+ const std::string& module) -+{ -+ std::ifstream in(verilog); -+ if (!in) { -+ throw std::runtime_error("cannot read " + verilog); -+ } -+ std::string text((std::istreambuf_iterator(in)), -+ std::istreambuf_iterator()); -+ std::regex head("\\bmodule\\s+" + module + "\\s*(#\\s*)?\\("); -+ std::smatch mh; -+ if (!std::regex_search(text, mh, head)) { -+ throw std::runtime_error("module " + module + " is not in " + verilog); -+ } -+ // From the header on, without comments, which may hold parentheses: a -+ // linear scan, as std::regex recurses per character and a generated -+ // core's Verilog runs to megabytes. -+ text = StripComments(text.substr(mh.position(0))); -+ if (!std::regex_search(text, mh, head) || mh.position(0) != 0) { -+ throw std::runtime_error("module " + module + ": cannot read its header"); -+ } -+ size_t open = mh.length(0) - 1; -+ size_t close = 0; -+ // A SystemVerilog parameter list, `#(parameter int W = 32, ...)`: its -+ // defaults size the ports. -+ std::map params; -+ if (mh[1].matched) { -+ std::string plist = Balanced(text, open, &close); -+ std::regex param( -+ "^\\s*(?:parameter|localparam)?\\s*(?:[A-Za-z_][A-Za-z_0-9:]*\\s+)*" -+ "(?:\\[[^\\]]*\\]\\s*)?([A-Za-z_][A-Za-z_0-9]*)\\s*=\\s*([\\s\\S]+?)" -+ "\\s*$"); -+ for (const auto& p : TopLevelCommas(plist)) { -+ std::smatch m; -+ if (std::regex_match(p, m, param)) { -+ try { -+ params[m[1].str()] = ConstExpr(m[2].str(), params).Eval(); -+ } catch (const std::runtime_error&) { -+ // A type or string parameter: no port width can use it here, -+ // and one that does fails below, naming it. -+ } -+ } -+ } -+ open = text.find('(', close + 1); -+ if (open == std::string::npos) { -+ throw std::runtime_error("module " + module + ": header never closes"); -+ } -+ } -+ std::string header = Balanced(text, open, &close); -+ // ANSI ports, one entry per comma: `input [4:0] a, b` declares two, the -+ // second inheriting the first's direction and width, whether it is on -+ // the same line or the next. Packed dimensions multiply. An entry that -+ // is not a port declaration this can read is an error, never skipped. -+ std::vector ports; -+ std::regex decl( -+ "^\\s*(input|output|inout)?\\s*(?:(?:wire|reg|logic|var|signed)\\s+)*" -+ "((?:\\[[^\\]]*\\]\\s*)*)" -+ "([A-Za-z_][A-Za-z_0-9$]*)\\s*$"); -+ std::regex dim("\\[([^:\\]]+):([^\\]]+)\\]"); -+ bool input = true; -+ int width = 1; -+ for (const auto& entry : TopLevelCommas(header)) { -+ if (entry.find_first_not_of(" \t\r\n") == std::string::npos) { -+ continue; -+ } -+ std::smatch m; -+ if (!std::regex_match(entry, m, decl)) { -+ throw std::runtime_error("module " + module -+ + ": cannot read the port declaration `" + entry -+ + "`"); -+ } -+ if (m[1].matched) { -+ input = m[1].str() != "output"; -+ width = 1; -+ } -+ const std::string dims = m[2].str(); -+ if (!dims.empty() || m[1].matched) { -+ width = 1; -+ for (std::sregex_iterator it(dims.begin(), dims.end(), dim), done; -+ it != done; -+ ++it) { -+ const long hi = ConstExpr((*it)[1].str(), params).Eval(); -+ const long lo = ConstExpr((*it)[2].str(), params).Eval(); -+ width *= static_cast(std::labs(hi - lo) + 1); -+ } -+ } -+ ports.push_back(RtlPort{m[3].str(), width, input}); -+ } -+ return ports; -+} -+ -+std::vector CheckPorts(const Spec& spec, -+ const std::vector& ports) -+{ -+ const int A = AddrWidth(spec.words); -+ std::map want; -+ want[spec.clock] = RtlPort{spec.clock, 1, true}; -+ if (!spec.reset.empty()) { -+ want[spec.reset] = RtlPort{spec.reset, 1, true}; -+ } -+ for (const auto& u : spec.unused) { -+ want[u] = RtlPort{u, 1, true}; -+ } -+ const int banks = std::max(spec.banks, 1); -+ const int A_bank = AddrWidth(spec.words / banks); -+ for (const auto& r : spec.read) { -+ if (r.banked()) { -+ for (size_t k = 0; k < r.bank_addr.size(); ++k) { -+ want[r.bank_addr[k]] = RtlPort{r.bank_addr[k], A_bank, true}; -+ want[r.bank_data[k]] = RtlPort{r.bank_data[k], spec.bits, false}; -+ } -+ } else { -+ want[r.addr] = RtlPort{r.addr, A, true}; -+ want[r.data] = RtlPort{r.data, spec.bits, false}; -+ } -+ } -+ for (const auto& w : spec.write) { -+ want[w.addr] = RtlPort{w.addr, A, true}; -+ want[w.data] = RtlPort{w.data, spec.bits, true}; -+ if (!w.en.empty()) { -+ want[w.en] = RtlPort{w.en, 1, true}; -+ } -+ } -+ std::map have; -+ for (const auto& p : ports) { -+ have[p.name] = p; -+ } -+ std::vector problems; -+ for (const auto& [name, w] : want) { -+ auto it = have.find(name); -+ if (it == have.end()) { -+ problems.push_back("spec names port " + name + ", the module has none"); -+ continue; -+ } -+ if (it->second.width != w.width) { -+ problems.push_back( -+ "port " + name + " is " + std::to_string(it->second.width) -+ + " bits in the module, " + std::to_string(w.width) + " in the spec"); -+ } -+ if (it->second.input != w.input) { -+ problems.push_back("port " + name + " is " -+ + (it->second.input ? "an input" : "an output") -+ + " in the module and the other way in the spec"); -+ } -+ } -+ for (const auto& [name, p] : have) { -+ if (want.find(name) == want.end()) { -+ problems.push_back("module port " + name + " is not in the spec"); -+ } -+ } -+ return problems; -+} -+ -+} // namespace ram::regfile -diff --git a/src/ram/src/views.h b/src/ram/src/views.h -new file mode 100644 -index 00000000000..4b312577e3b ---- /dev/null -+++ b/src/ram/src/views.h -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+// Copyright (c) 2026, The OpenROAD Authors -+ -+// generate_regfile: the views a parent's flow consumes before the block is -+// routed -- an abstract LEF from the placed block and a model liberty -- -+// and the check that a spec's ports are the RTL module's. -+// -+// The lib is a model, the way FakeRAM's is, so it lands in seconds inside -+// the parent's synthesis: pin loads from fanout, arcs from the known gate -+// depth of the read and write paths, a constant leakage per cell. It is -+// replaced by the routed block's own abstract for a measured run; the -+// numbers here are written so that swap changes as little as possible. -+#pragma once -+ -+#include -+#include -+ -+#include "regfile.h" -+ -+namespace odb { -+class dbBlock; -+} -+ -+namespace utl { -+class Logger; -+} -+ -+namespace ram::regfile { -+ -+// Abstract LEF of the placed block: outline, pins, obstruction on every -+// layer the cells occupy. Bloats the occupied layers into one obstruction, -+// as write_abstract_lef -bloat_occupied_layers does. -+void WriteLef(odb::dbBlock* block, -+ utl::Logger* logger, -+ const std::string& path); -+ -+// Model liberty for the generated block, see LibModel. `pre_layout` only -+// changes the comment: the model has no clock tree to be ideal about. -+void WriteLiberty(odb::dbBlock* block, -+ const Spec& spec, -+ const LibModel& model, -+ const std::string& path, -+ bool pre_layout); -+ -+// One RTL port as declared: name, width in bits (1 for a scalar), input? -+struct RtlPort -+{ -+ std::string name; -+ int width = 1; -+ bool input = true; -+}; -+ -+// The ports of `module` in a Verilog file, firtool's declaration style: -+// ANSI header, and consecutive same-direction ports packed on bare -+// continuation lines that inherit direction and width. Throws -+// std::runtime_error when the module is not in the file. -+std::vector ReadModulePorts(const std::string& verilog, -+ const std::string& module); -+ -+// Refuses, with every difference named, a spec whose ports are not the -+// module's: a port the spec names that the module lacks, a width that -+// differs, a direction that differs, or a module port the spec never -+// mentions. Returns the list of problems; empty means they agree. -+std::vector CheckPorts(const Spec& spec, -+ const std::vector& ports); -+ -+} // namespace ram::regfile -diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index 071fa2c0f0b..9a834644a3e 100644 ---- a/src/ram/test/BUILD -+++ b/src/ram/test/BUILD -@@ -13,10 +13,27 @@ COMPULSORY_TESTS = [ - ] - - PASSFAIL_TESTS = [ -+ "generate_regfile_asap7", -+ "generate_regfile_clock_gate_asap7", -+ "generate_regfile_modes_asap7", -+ "generate_regfile_reset_asap7", -+ "generate_regfile_reset_high_asap7", -+ "generate_regfile_sv_ports_asap7", -+ "generate_regfile_write_priority_asap7", - ] - - ALL_TESTS = COMPULSORY_TESTS + PASSFAIL_TESTS - -+# What every generate_regfile test reads: the asap7 cells, their -+# liberty for constant propagation, the base spec's module. Every test -+# but generate_regfile_asap7 (whose own glob has it) adds the spec. -+REGFILE_TEST_DATA = [ -+ "//test:asap7_data", -+ "//test:asap7_nldm_data", -+ "generate_regfile_asap7_rtl.v", -+ "regfile_checks.tcl", -+] -+ - filegroup( - name = "regression_resources", - # Dependencies could be specified more narrowly per test case, -@@ -51,6 +73,28 @@ filegroup( - test_name + ".*", - ], - ) + { -+ "generate_regfile_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7_rtl_extra.v", -+ ], -+ "generate_regfile_clock_gate_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7.regfile", -+ ], -+ "generate_regfile_modes_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7.regfile", -+ ], -+ "generate_regfile_reset_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7.regfile", -+ ], -+ "generate_regfile_reset_high_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7.regfile", -+ ], -+ "generate_regfile_sv_ports_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7.regfile", -+ "generate_regfile_sv_ports_asap7_rtl.sv", -+ ], -+ "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ -+ "generate_regfile_asap7.regfile", -+ ], - "make_7x7_2r1w_nangate45": [ - "make_7x7_2r1w_nangate45_behavioral.vok", - "Nangate45/Nangate45.lef", -diff --git a/src/ram/test/CMakeLists.txt b/src/ram/test/CMakeLists.txt -index 8545b3dbca9..a02f25bf641 100644 ---- a/src/ram/test/CMakeLists.txt -+++ b/src/ram/test/CMakeLists.txt -@@ -5,5 +5,12 @@ or_integration_tests( - # golden .defok matches the clang build used by bazel, not the gcc - # build typically used by cmake. See src/ram/test/BUILD. - make_7x7_nangate45 -+ PASSFAIL_TESTS -+ generate_regfile_asap7 -+ generate_regfile_clock_gate_asap7 -+ generate_regfile_modes_asap7 -+ generate_regfile_reset_asap7 -+ generate_regfile_reset_high_asap7 -+ generate_regfile_sv_ports_asap7 -+ generate_regfile_write_priority_asap7 - ) -- -diff --git a/src/ram/test/generate_regfile_asap7.regfile b/src/ram/test/generate_regfile_asap7.regfile -new file mode 100644 -index 00000000000..ad31829371c ---- /dev/null -+++ b/src/ram/test/generate_regfile_asap7.regfile -@@ -0,0 +1,22 @@ -+# An 8 x 4 register file, two read and two write ports, in two banks, -+# with word 0 reading zero, laid out for a parent that places its decode -+# (mode netlist). -+module rf8x4 -+mode netlist -+words 8 -+bits 4 -+banks 2 -+clock clock -+read r0_addr r0_data -+read r1_addr r1_data -+write w0_addr w0_data w0_en -+write w1_addr w1_data w1_en -+zero_word 0 -+cell flop DFFHQNx1_ASAP7_75t_R -+cell and2 AND2x2_ASAP7_75t_R -+cell or2 OR2x2_ASAP7_75t_R -+cell ao22 AO22x2_ASAP7_75t_R -+cell inv INVx1_ASAP7_75t_R -+cell tap TAPCELL_ASAP7_75t_R -+pin_layer M4 -+tap_columns 2 -diff --git a/src/ram/test/generate_regfile_asap7.tcl b/src/ram/test/generate_regfile_asap7.tcl -new file mode 100644 -index 00000000000..2e26e14c4d8 ---- /dev/null -+++ b/src/ram/test/generate_regfile_asap7.tcl -@@ -0,0 +1,87 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_asap7 -+# generate_regfile builds the register file its spec describes: every -+# read port reads every word, word 0 reads zero, a write port loads only -+# the word it addresses and every other word holds, and the abstract and -+# the timing model name every port. A spec whose ports are not the RTL -+# module's is refused. Checked by constant propagation through the -+# generated cells, not against a golden netlist. -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+ -+set failed [catch { -+ tee -quiet -variable log { -+ generate_regfile -spec generate_regfile_asap7.regfile \ -+ -check_ports generate_regfile_asap7_rtl_extra.v -+ } -+} message] -+check "a port the spec does not name is refused" { set failed } 1 -+check "the refusal is RAM-0050" { string match "*RAM-0050*" $message } 1 -+check "the refusal names the port" \ -+ { string match "*module port w2_en is not in the spec*" $log } 1 -+ -+set lef_file [make_result_file generate_regfile_asap7.lef] -+set lib_file [make_result_file generate_regfile_asap7.lib] -+tee -quiet -variable gen_log [list generate_regfile \ -+ -spec generate_regfile_asap7.regfile \ -+ -check_ports generate_regfile_asap7_rtl.v \ -+ -lef $lef_file -liberty $lib_file] -+ -+# mode netlist: the generator fixes the core and leaves the periphery -+# (address inverters, decode, hold) to the parent, which places, sizes -+# and buffers it with the drivers and loads outside the array. -+set placement [rf_placement] -+check "mode netlist fixes every storage flop" \ -+ { dict get $placement flops_not_fixed } 0 -+check "mode netlist leaves the periphery unplaced" \ -+ { expr { [dict get $placement unplaced] > 0 } } 1 -+check "and says so" { string match "*RAM-0052*mode netlist*" $gen_log } 1 -+ -+set words 8 -+set bits 4 -+set abits 3 -+for { set w 1 } { $w < $words } { incr w } { -+ rf_store $w $bits [rf_word_value $w $bits] -+} -+ -+foreach port { r0 r1 } { -+ for { set a 0 } { $a < $words } { incr a } { -+ rf_drive ${port}_addr $abits $a -+ set expected [expr { $a == 0 ? 0 : [rf_word_value $a $bits] }] -+ check "$port reads word $a" { rf_read ${port}_data $bits } $expected -+ } -+} -+ -+# With a hold term per bit (write_style mux, the default) a word's flops -+# load the write data when the word is written and their own value -+# otherwise. -+proc check_writes { port other } { -+ rf_drive_bit ${other}_en 0 -+ rf_drive_bit ${port}_en 1 -+ foreach a { 1 3 6 } { -+ set data [expr { (~[rf_word_value $a 4]) & 15 }] -+ rf_drive ${port}_addr 3 $a -+ rf_drive ${port}_data 4 $data -+ for { set w 1 } { $w < 8 } { incr w } { -+ set expected [expr { $w == $a ? $data : [rf_word_value $w 4] }] -+ check "$port writing word $a: word $w loads" { rf_next $w 4 } $expected -+ } -+ } -+ rf_drive_bit ${port}_en 0 -+ for { set w 1 } { $w < 8 } { incr w } { -+ check "no write: word $w holds" { rf_next $w 4 } [rf_word_value $w 4] -+ } -+} -+check_writes w0 w1 -+check_writes w1 w0 -+ -+check "the abstract names every port" { rf_ports_missing_from $lef_file lef } {} -+check "the timing model names every port" \ -+ { rf_ports_missing_from $lib_file lib } {} -+ -+exit_summary -diff --git a/src/ram/test/generate_regfile_asap7_rtl.v b/src/ram/test/generate_regfile_asap7_rtl.v -new file mode 100644 -index 00000000000..36a3e3a9993 ---- /dev/null -+++ b/src/ram/test/generate_regfile_asap7_rtl.v -@@ -0,0 +1,8 @@ -+// The module generate_regfile_asap7.regfile describes, its ports -+// declared several to a line, as hand-written RTL often does. -+module rf8x4 (input clock, -+ input [2:0] r0_addr, r1_addr, -+ output [3:0] r0_data, r1_data, -+ input [2:0] w0_addr, input [3:0] w0_data, input w0_en, -+ input [2:0] w1_addr, input [3:0] w1_data, input w1_en); -+endmodule -diff --git a/src/ram/test/generate_regfile_asap7_rtl_extra.v b/src/ram/test/generate_regfile_asap7_rtl_extra.v -new file mode 100644 -index 00000000000..688dd3ac99c ---- /dev/null -+++ b/src/ram/test/generate_regfile_asap7_rtl_extra.v -@@ -0,0 +1,9 @@ -+// generate_regfile_asap7_rtl.v with a port the spec does not name -+// (w2_en): the port check must refuse the spec. -+module rf8x4 (input clock, -+ input [2:0] r0_addr, r1_addr, -+ output [3:0] r0_data, r1_data, -+ input [2:0] w0_addr, input [3:0] w0_data, input w0_en, -+ input [2:0] w1_addr, input [3:0] w1_data, input w1_en, -+ input w2_en); -+endmodule -diff --git a/src/ram/test/generate_regfile_clock_gate_asap7.tcl b/src/ram/test/generate_regfile_clock_gate_asap7.tcl -new file mode 100644 -index 00000000000..3707bb41402 ---- /dev/null -+++ b/src/ram/test/generate_regfile_clock_gate_asap7.tcl -@@ -0,0 +1,50 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_clock_gate_asap7 -+# generate_regfile with a clock gate per word (write_style clock_gate): -+# every read port reads every word, and a write opens the clock gate of -+# the word it addresses, and only that one, with the write data on its -+# flops' D. Checked by constant propagation through the generated cells. -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+set spec [rf_spec generate_regfile_asap7.regfile \ -+ generate_regfile_clock_gate_asap7.regfile {"write_style clock_gate"}] -+generate_regfile -spec $spec -check_ports generate_regfile_asap7_rtl.v -+ -+for { set w 1 } { $w < 8 } { incr w } { -+ rf_store $w 4 [rf_word_value $w 4] -+} -+foreach port { r0 r1 } { -+ for { set a 0 } { $a < 8 } { incr a } { -+ rf_drive ${port}_addr 3 $a -+ set expected [expr { $a == 0 ? 0 : [rf_word_value $a 4] }] -+ check "$port reads word $a" { rf_read ${port}_data 4 } $expected -+ } -+} -+ -+proc check_writes { port other } { -+ rf_drive_bit ${other}_en 0 -+ rf_drive_bit ${port}_en 1 -+ foreach a { 1 3 6 } { -+ set data [expr { (~[rf_word_value $a 4]) & 15 }] -+ rf_drive ${port}_addr 3 $a -+ rf_drive ${port}_data 4 $data -+ for { set w 1 } { $w < 8 } { incr w } { -+ check "$port writing word $a: word $w's clock gate" \ -+ { rf_value w${w}_icg/ENA } [expr { $w == $a ? 1 : 0 }] -+ } -+ check "$port writing word $a: its flops load the data" { rf_next $a 4 } $data -+ } -+ rf_drive_bit ${port}_en 0 -+ for { set w 1 } { $w < 8 } { incr w } { -+ check "no write: word $w's clock gate is shut" { rf_value w${w}_icg/ENA } 0 -+ } -+} -+check_writes w0 w1 -+check_writes w1 w0 -+ -+exit_summary -diff --git a/src/ram/test/generate_regfile_modes_asap7.tcl b/src/ram/test/generate_regfile_modes_asap7.tcl -new file mode 100644 -index 00000000000..6ac445d0755 ---- /dev/null -+++ b/src/ram/test/generate_regfile_modes_asap7.tcl -@@ -0,0 +1,28 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_modes_asap7 -+# mode macro: the register file is a macro to its parent, every instance -+# placed by the generator, none left to the parent, and nothing to say -+# about it. (mode netlist, which leaves the periphery to the parent, is -+# checked by generate_regfile_asap7.) -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+ -+set spec [rf_spec generate_regfile_asap7.regfile \ -+ generate_regfile_modes_asap7.regfile {"mode macro"}] -+tee -quiet -variable gen_log [list generate_regfile \ -+ -spec $spec -check_ports generate_regfile_asap7_rtl.v] -+ -+set placement [rf_placement] -+check "mode macro places every instance" \ -+ { dict get $placement unplaced } 0 -+check "mode macro fixes every storage flop" \ -+ { dict get $placement flops_not_fixed } 0 -+check "mode macro reports nothing left unplaced" \ -+ { string match "*RAM-0052*" $gen_log } 0 -+ -+exit_summary -diff --git a/src/ram/test/generate_regfile_reset_asap7.tcl b/src/ram/test/generate_regfile_reset_asap7.tcl -new file mode 100644 -index 00000000000..0830ae2680f ---- /dev/null -+++ b/src/ram/test/generate_regfile_reset_asap7.tcl -@@ -0,0 +1,55 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_reset_asap7 -+# generate_regfile with an asynchronous reset, active low (async_reset -+# rst_n low): every storage flop is the spec's reset flop, its reset -+# (RESETN, which clears the stored value) is asserted exactly while rst_n -+# is active, its set is tied off, and the file reads its words once reset -+# is released. Checked by constant propagation through the generated -+# cells. -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+set spec [rf_spec generate_regfile_asap7.regfile generate_regfile_reset_asap7.regfile { -+ "async_reset rst_n low" -+ "cell flop_r DFFASRHQNx1_ASAP7_75t_R" -+ "cell tie_hi TIEHIx1_ASAP7_75t_R" -+}] -+generate_regfile -spec $spec -+ -+set flops {} -+for { set w 1 } { $w < 8 } { incr w } { -+ for { set b 0 } { $b < 4 } { incr b } { -+ lappend flops w${w}_b${b}_ff -+ } -+} -+set flop_r [[ord::get_db] findMaster DFFASRHQNx1_ASAP7_75t_R] -+foreach ff $flops { -+ check "$ff is the reset flop" \ -+ { [[ord::get_db_block] findInst $ff] getMaster } $flop_r -+} -+ -+proc check_reset { flops state value } { -+ foreach ff $flops { -+ check "rst_n $state: $ff RESETN" { rf_value $ff/RESETN } $value -+ check "rst_n $state: $ff SETN is tied off" { rf_value $ff/SETN } 1 -+ } -+} -+rf_drive_bit rst_n 0 -+check_reset $flops active 0 -+rf_drive_bit rst_n 1 -+check_reset $flops released 1 -+ -+for { set w 1 } { $w < 8 } { incr w } { -+ rf_store $w 4 [rf_word_value $w 4] -+} -+for { set a 0 } { $a < 8 } { incr a } { -+ rf_drive r0_addr 3 $a -+ set expected [expr { $a == 0 ? 0 : [rf_word_value $a 4] }] -+ check "released: r0 reads word $a" { rf_read r0_data 4 } $expected -+} -+ -+exit_summary -diff --git a/src/ram/test/generate_regfile_reset_high_asap7.tcl b/src/ram/test/generate_regfile_reset_high_asap7.tcl -new file mode 100644 -index 00000000000..da87418cd4a ---- /dev/null -+++ b/src/ram/test/generate_regfile_reset_high_asap7.tcl -@@ -0,0 +1,55 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_reset_high_asap7 -+# generate_regfile with an asynchronous reset, active high (async_reset -+# rst high): every storage flop is the spec's reset flop, its reset -+# (RESETN, which clears the stored value) is asserted exactly while rst -+# is active, its set is tied off, and the file reads its words once reset -+# is released. Checked by constant propagation through the generated -+# cells. -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+set spec [rf_spec generate_regfile_asap7.regfile generate_regfile_reset_high_asap7.regfile { -+ "async_reset rst high" -+ "cell flop_r DFFASRHQNx1_ASAP7_75t_R" -+ "cell tie_hi TIEHIx1_ASAP7_75t_R" -+}] -+generate_regfile -spec $spec -+ -+set flops {} -+for { set w 1 } { $w < 8 } { incr w } { -+ for { set b 0 } { $b < 4 } { incr b } { -+ lappend flops w${w}_b${b}_ff -+ } -+} -+set flop_r [[ord::get_db] findMaster DFFASRHQNx1_ASAP7_75t_R] -+foreach ff $flops { -+ check "$ff is the reset flop" \ -+ { [[ord::get_db_block] findInst $ff] getMaster } $flop_r -+} -+ -+proc check_reset { flops state value } { -+ foreach ff $flops { -+ check "rst $state: $ff RESETN" { rf_value $ff/RESETN } $value -+ check "rst $state: $ff SETN is tied off" { rf_value $ff/SETN } 1 -+ } -+} -+rf_drive_bit rst 1 -+check_reset $flops active 0 -+rf_drive_bit rst 0 -+check_reset $flops released 1 -+ -+for { set w 1 } { $w < 8 } { incr w } { -+ rf_store $w 4 [rf_word_value $w 4] -+} -+for { set a 0 } { $a < 8 } { incr a } { -+ rf_drive r0_addr 3 $a -+ set expected [expr { $a == 0 ? 0 : [rf_word_value $a 4] }] -+ check "released: r0 reads word $a" { rf_read r0_data 4 } $expected -+} -+ -+exit_summary -diff --git a/src/ram/test/generate_regfile_sv_ports_asap7.tcl b/src/ram/test/generate_regfile_sv_ports_asap7.tcl -new file mode 100644 -index 00000000000..ef43a8c13b7 ---- /dev/null -+++ b/src/ram/test/generate_regfile_sv_ports_asap7.tcl -@@ -0,0 +1,64 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_sv_ports_asap7 -+# The port check reads a SystemVerilog module header: a #(...) parameter -+# list, port widths written in the parameters' defaults, and an input the -+# register file does not use (`unused`). It refuses a width that differs -+# once the parameters are evaluated, and a declaration it cannot read, -+# rather than skipping it. -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+set spec [rf_spec generate_regfile_asap7.regfile \ -+ generate_regfile_sv_ports_asap7.regfile {"unused test_en_i"}] -+ -+# The same module with other text: a copy of the RTL in the results dir. -+proc rtl_variant { name from to } { -+ set in [open generate_regfile_sv_ports_asap7_rtl.sv r] -+ set text [read $in] -+ close $in -+ set file [make_result_file $name] -+ set out [open $file w] -+ puts -nonewline $out [string map [list $from $to] $text] -+ close $out -+ return $file -+} -+ -+# generate_regfile's error and its log for `rtl`; tee runs its script -+# unsubstituted, so the command is built first. -+proc refusal { rtl } { -+ global spec -+ set cmd [list generate_regfile -spec $spec -check_ports $rtl] -+ set failed [catch { tee -quiet -variable log $cmd } message] -+ return [list $failed $message $log] -+} -+ -+lassign [refusal [rtl_variant wide.sv "W = 4" "W = 8"]] failed message log -+check "a width that differs once W is evaluated is refused" { set failed } 1 -+check "the refusal is RAM-0050" { string match "*RAM-0050*" $message } 1 -+check "the refusal names the port and both widths" \ -+ { string match "*port r0_data is 8 bits in the module, 4 in the spec*" $log } 1 -+ -+lassign [refusal [rtl_variant typed.sv "logic \[A-1:0\] r1_addr" \ -+ "rf_pkg::addr_t r1_addr"]] failed message log -+check "a declaration the check cannot read is refused" { set failed } 1 -+check "the refusal quotes it" \ -+ { string match "*cannot read the port declaration*rf_pkg::addr_t r1_addr*" $log } 1 -+ -+generate_regfile -spec $spec -check_ports generate_regfile_sv_ports_asap7_rtl.sv -+check "the unused input is a port of the register file" \ -+ { expr { [[ord::get_db_block] findBTerm test_en_i] ne "NULL" } } 1 -+ -+for { set w 1 } { $w < 8 } { incr w } { -+ rf_store $w 4 [rf_word_value $w 4] -+} -+for { set a 0 } { $a < 8 } { incr a } { -+ rf_drive r1_addr 3 $a -+ set expected [expr { $a == 0 ? 0 : [rf_word_value $a 4] }] -+ check "r1 reads word $a" { rf_read r1_data 4 } $expected -+} -+ -+exit_summary -diff --git a/src/ram/test/generate_regfile_sv_ports_asap7_rtl.sv b/src/ram/test/generate_regfile_sv_ports_asap7_rtl.sv -new file mode 100644 -index 00000000000..bfda9bdd337 ---- /dev/null -+++ b/src/ram/test/generate_regfile_sv_ports_asap7_rtl.sv -@@ -0,0 +1,20 @@ -+// rf8x4 as a SystemVerilog module: a parameter list, port widths written -+// in its parameters, and an input the register file does not use. -+module rf8x4 #( -+ parameter int unsigned W = 4, -+ parameter int unsigned A = 3 -+) ( -+ input logic clock, -+ input logic test_en_i, -+ input logic [A-1:0] r0_addr, -+ output logic [W-1:0] r0_data, -+ input logic [A-1:0] r1_addr, -+ output logic [W-1:0] r1_data, -+ input logic [A-1:0] w0_addr, -+ input logic [W-1:0] w0_data, -+ input logic w0_en, -+ input logic [A-1:0] w1_addr, -+ input logic [W-1:0] w1_data, -+ input logic w1_en -+); -+endmodule -diff --git a/src/ram/test/generate_regfile_write_priority_asap7.tcl b/src/ram/test/generate_regfile_write_priority_asap7.tcl -new file mode 100644 -index 00000000000..39374756281 ---- /dev/null -+++ b/src/ram/test/generate_regfile_write_priority_asap7.tcl -@@ -0,0 +1,36 @@ -+# SPDX-License-Identifier: BSD-3-Clause -+# Copyright (c) 2026, The OpenROAD Authors -+# -+# Test: ram/generate_regfile_write_priority_asap7 -+# generate_regfile with `write_priority last`: when both write ports -+# write one word in one cycle, the word loads the later port's data; -+# writes to different words each load their own. Checked by constant -+# propagation through the generated cells. -+ -+source "helpers.tcl" -+source "regfile_checks.tcl" -+ -+rf_read_libraries -+set spec [rf_spec generate_regfile_asap7.regfile \ -+ generate_regfile_write_priority_asap7.regfile {"write_priority last"}] -+generate_regfile -spec $spec -check_ports generate_regfile_asap7_rtl.v -+ -+for { set w 1 } { $w < 8 } { incr w } { -+ rf_store $w 4 [rf_word_value $w 4] -+} -+rf_drive_bit w0_en 1 -+rf_drive_bit w1_en 1 -+foreach a { 1 4 7 } { -+ rf_drive w0_addr 3 $a -+ rf_drive w1_addr 3 $a -+ rf_drive w0_data 4 5 -+ rf_drive w1_data 4 10 -+ check "both ports write word $a: it loads w1's data" { rf_next $a 4 } 10 -+} -+rf_drive w0_addr 3 2 -+rf_drive w1_addr 3 6 -+check "w0 writes word 2: it loads w0's data" { rf_next 2 4 } 5 -+check "w1 writes word 6: it loads w1's data" { rf_next 6 4 } 10 -+check "word 3 holds" { rf_next 3 4 } [rf_word_value 3 4] -+ -+exit_summary -diff --git a/src/ram/test/regfile_checks.tcl b/src/ram/test/regfile_checks.tcl -new file mode 100644 -index 00000000000..56b5ae3ce8a ---- /dev/null -+++ b/src/ram/test/regfile_checks.tcl -@@ -0,0 +1,136 @@ -+# Checks of a generated register file by what it computes, not by how it -+# is laid out: case analysis on its inputs and on its storage, and -+# OpenSTA's constant propagation through its cells. Sourced by the -+# generate_regfile tests after helpers.tcl. -+ -+proc rf_read_libraries { } { -+ read_lef ../../../test/asap7/asap7_tech_1x_201209.lef -+ read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef -+ foreach kind { AO OA SIMPLE } { -+ read_liberty ../../../test/asap7/asap7sc7p5t_${kind}_RVT_FF_nldm_211120.lib.gz -+ } -+ read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz -+ read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib -+} -+ -+# A spec file: the base spec with `lines` appended, in the results dir. -+proc rf_spec { base name lines } { -+ set spec [make_result_file $name] -+ set out [open $spec w] -+ set in [open $base r] -+ puts -nonewline $out [read $in] -+ close $in -+ foreach line $lines { -+ puts $out $line -+ } -+ close $out -+ return $spec -+} -+ -+# The propagated value of a port (by name) or an instance pin. -+proc rf_value { name } { -+ set port [get_ports -quiet $name] -+ if { $port ne "" } { -+ return [sta::pin_sim_logic_value [sta::get_port_pin $port]] -+ } -+ return [sta::pin_sim_logic_value [get_pins $name]] -+} -+ -+proc rf_drive_bit { name value } { -+ set_case_analysis $value [get_ports $name] -+} -+ -+proc rf_drive { bus width value } { -+ for { set i 0 } { $i < $width } { incr i } { -+ rf_drive_bit "$bus\[$i\]" [expr { ($value >> $i) & 1 }] -+ } -+} -+ -+# The integer an output bus carries, or X if any bit is not a constant. -+proc rf_read { bus width } { -+ set v 0 -+ for { set i 0 } { $i < $width } { incr i } { -+ set b [rf_value "$bus\[$i\]"] -+ if { $b ne "0" && $b ne "1" } { -+ return X -+ } -+ set v [expr { $v | ($b << $i) }] -+ } -+ return $v -+} -+ -+# Word `word` holding `value`: the storage flop of each bit holds the -+# inverse on QN, which is where the value is set. -+proc rf_store { word bits value } { -+ for { set b 0 } { $b < $bits } { incr b } { -+ set_case_analysis [expr { 1 - (($value >> $b) & 1) }] \ -+ [get_pins w${word}_b${b}_ff/QN] -+ } -+} -+ -+# The integer word `word`'s flops would load: their D inputs. -+proc rf_next { word bits } { -+ set v 0 -+ for { set b 0 } { $b < $bits } { incr b } { -+ set d [rf_value w${word}_b${b}_ff/D] -+ if { $d ne "0" && $d ne "1" } { -+ return X -+ } -+ set v [expr { $v | ($d << $b) }] -+ } -+ return $v -+} -+ -+# A value per word, distinct across words, for the storage. -+proc rf_word_value { word bits } { -+ return [expr { ($word * 5 + 3) & ((1 << $bits) - 1) }] -+} -+ -+# The ports of the generated block missing from a view: the abstract -+# (`PIN `) or the timing model (`pin()`, or a `bus()` -+# for a bus bit). -+proc rf_ports_missing_from { file kind } { -+ set in [open $file r] -+ set text [read $in] -+ close $in -+ set missing {} -+ foreach bterm [[ord::get_db_block] getBTerms] { -+ set name [$bterm getName] -+ set base [lindex [split $name {[}] 0] -+ if { $kind eq "lef" } { -+ set found [expr { [string first "PIN $name\n" $text] >= 0 }] -+ } else { -+ set found [expr { -+ [string first "pin($name)" $text] >= 0 -+ || [string first "bus($base)" $text] >= 0 -+ }] -+ } -+ if { !$found } { -+ lappend missing $name -+ } -+ } -+ return $missing -+} -+ -+# The block's instances by placement: fixed, placed (movable) and -+# unplaced, and how many of the storage flops (DFF*) are not fixed. -+proc rf_placement { } { -+ set n [dict create fixed 0 placed 0 unplaced 0 flops_not_fixed 0] -+ foreach inst [[ord::get_db_block] getInsts] { -+ set status [$inst getPlacementStatus] -+ if { $status == "FIRM" || $status == "LOCKED" || $status == "COVER" } { -+ dict incr n fixed -+ } elseif { $status == "PLACED" || $status == "SUGGESTED" } { -+ dict incr n placed -+ } else { -+ dict incr n unplaced -+ } -+ if { -+ [string match "DFF*" [[$inst getMaster] getName]] -+ && $status != "FIRM" -+ } { -+ dict incr n flops_not_fixed -+ } -+ } -+ return $n -+} -diff --git a/test/BUILD b/test/BUILD ---- a/test/BUILD -+++ b/test/BUILD -@@ -102,6 +102,20 @@ filegroup( - ], - visibility = ["//visibility:public"], - ) -+ -+# asap7's NLDM liberty, for the cells' functions: generate_regfile's -+# tests read them through OpenSTA's constant propagation. -+filegroup( -+ name = "asap7_nldm_data", -+ srcs = [ -+ "asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz", -+ "asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz", -+ "asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz", -+ "asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib", -+ "asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz", -+ ], -+ visibility = ["//visibility:public"], -+) - - # CCS (current source model) liberty. Required by delay calculators that need - # output current waveforms, e.g. prima; the asap7 libs above are NLDM only. diff --git a/patches/0011-openroad-ram-multiple-write-ports.patch b/patches/0011-openroad-ram-multiple-write-ports.patch index d00f0cb19..9b9295854 100644 --- a/patches/0011-openroad-ram-multiple-write-ports.patch +++ b/patches/0011-openroad-ram-multiple-write-ports.patch @@ -21,7 +21,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 1c921505d2..008107da2d 100644 +index 94c5df3036..dc03e5b6cb 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -62,9 +62,9 @@ generate_ram [-mask_size bits] @@ -990,7 +990,7 @@ index 2d2c537800..7e97ae2600 100644 std::ofstream vf(filename); diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 505b551342..6ca3a68023 100644 +index 4e58c50163..98f5e607ad 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -87,8 +87,12 @@ proc generate_ram_netlist { args } { @@ -1026,7 +1026,7 @@ index 505b551342..6ca3a68023 100644 set max_tap_dist 0 if { [info exists keys(-tapcell)] } { diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index 2e4ff86aba..cec5372c33 100644 +index 071fa2c0f0..af915fc087 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -1034,13 +1034,13 @@ index 2e4ff86aba..cec5372c33 100644 PASSFAIL_TESTS = [ + "make_7x7_1r2w_nangate45", - "generate_regfile_asap7", - "generate_regfile_clock_gate_asap7", - "generate_regfile_modes_asap7", -@@ -90,6 +91,12 @@ filegroup( - "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ - "generate_regfile_asap7.regfile", + ] + + ALL_TESTS = COMPULSORY_TESTS + PASSFAIL_TESTS +@@ -51,6 +52,12 @@ filegroup( + test_name + ".*", ], + ) + { + "make_7x7_1r2w_nangate45": [ + "make_7x7_1r2w_nangate45_behavioral.vok", + "Nangate45/Nangate45.lef", diff --git a/patches/0012-openroad-ram-and-or-read.patch b/patches/0012-openroad-ram-and-or-read.patch index 79c059d92..cc575ca20 100644 --- a/patches/0012-openroad-ram-and-or-read.patch +++ b/patches/0012-openroad-ram-and-or-read.patch @@ -24,7 +24,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 008107da2d..f7981d19fc 100644 +index dc03e5b6cb..b289c8104b 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -43,6 +43,7 @@ generate_ram [-mask_size bits] @@ -676,10 +676,10 @@ index 7e97ae2600..463e1f3a86 100644 // one select_b_net per row for column_mux_ratio > 1 vector shared_select_b_nets(r_total); diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index c4584484fa..fed815886b 100644 +index 8b225fcc89..bb90a0c434 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -42,7 +42,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -41,7 +41,8 @@ generate_ram_netlist_cmd(int mask_size, const char* tristate_cell_name, const char* inv_cell_name, const char* tapcell_name, @@ -689,7 +689,7 @@ index c4584484fa..fed815886b 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -94,7 +95,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -93,7 +94,7 @@ generate_ram_netlist_cmd(int mask_size, ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, @@ -697,9 +697,9 @@ index c4584484fa..fed815886b 100644 + tapcell, max_tap_dist, read_style); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 6ca3a68023..2eb5896319 100644 +index 98f5e607ad..8ae362eb9e 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -7,6 +7,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -769,7 +769,7 @@ index 6ca3a68023..2eb5896319 100644 lappend ram_netlist_args -inv_cell $keys(-inv_cell) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index cec5372c33..87d3ef72a7 100644 +index af915fc087..5fe9d8b0a3 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -778,12 +778,12 @@ index cec5372c33..87d3ef72a7 100644 PASSFAIL_TESTS = [ + "make_8x8_2r1w_and_or_asap7", "make_7x7_1r2w_nangate45", - "generate_regfile_asap7", - "generate_regfile_clock_gate_asap7", -@@ -91,6 +92,11 @@ filegroup( - "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ - "generate_regfile_asap7.regfile", + ] + +@@ -52,6 +53,11 @@ filegroup( + test_name + ".*", ], + ) + { + "make_8x8_2r1w_and_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", @@ -1566,3 +1566,28 @@ index d6ce26bfc6..cb958fabc3 100644 + make_8x8_2r1w_and_or_asap7 make_8x8_latch_sky130 } +diff --git a/test/BUILD b/test/BUILD +index 66146170ea..01eac4066a 100644 +--- a/test/BUILD ++++ b/test/BUILD +@@ -103,6 +103,20 @@ filegroup( + visibility = ["//visibility:public"], + ) + ++# asap7's NLDM liberty, for the cells' functions: the ram module's asap7 ++# tests find their cells by them. ++filegroup( ++ name = "asap7_nldm_data", ++ srcs = [ ++ "asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz", ++ "asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz", ++ "asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz", ++ "asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib", ++ "asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz", ++ ], ++ visibility = ["//visibility:public"], ++) ++ + # CCS (current source model) liberty. Required by delay calculators that need + # output current waveforms, e.g. prima; the asap7 libs above are NLDM only. + # Holds four cells: AND2x2, BUFx2, DFFHQx4, INVx2. diff --git a/patches/0013-openroad-ram-zero-word.patch b/patches/0013-openroad-ram-zero-word.patch index 1a7d23b57..9785b5e75 100644 --- a/patches/0013-openroad-ram-zero-word.patch +++ b/patches/0013-openroad-ram-zero-word.patch @@ -14,7 +14,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index f7981d19fc..c73f269d6c 100644 +index b289c8104b..6702d6699a 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -44,6 +44,7 @@ generate_ram [-mask_size bits] @@ -312,10 +312,10 @@ index 463e1f3a86..7362a35c8e 100644 mask_size, mask_size, diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index fed815886b..5f765b215b 100644 +index bb90a0c434..35f5bf3157 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -43,7 +43,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -42,7 +42,8 @@ generate_ram_netlist_cmd(int mask_size, const char* inv_cell_name, const char* tapcell_name, const int max_tap_dist, @@ -325,7 +325,7 @@ index fed815886b..5f765b215b 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -95,7 +96,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -94,7 +95,7 @@ generate_ram_netlist_cmd(int mask_size, ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, @@ -333,9 +333,9 @@ index fed815886b..5f765b215b 100644 + tapcell, max_tap_dist, read_style, zero_word); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 2eb5896319..998f61fde5 100644 +index 8ae362eb9e..2494d4c873 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -8,6 +8,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -394,7 +394,7 @@ index 2eb5896319..998f61fde5 100644 lappend ram_netlist_args -inv_cell $keys(-inv_cell) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index 87d3ef72a7..0bd0331ed9 100644 +index 5fe9d8b0a3..1192665493 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -404,11 +404,11 @@ index 87d3ef72a7..0bd0331ed9 100644 + "make_8x8_2r1w_zero_asap7", "make_8x8_2r1w_and_or_asap7", "make_7x7_1r2w_nangate45", - "generate_regfile_asap7", -@@ -92,6 +93,11 @@ filegroup( - "generate_regfile_write_priority_asap7": REGFILE_TEST_DATA + [ - "generate_regfile_asap7.regfile", + ] +@@ -53,6 +54,11 @@ filegroup( + test_name + ".*", ], + ) + { + "make_8x8_2r1w_zero_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", diff --git a/patches/0014-openroad-ram-reset.patch b/patches/0014-openroad-ram-reset.patch index 4092650d2..c4efc2d6e 100644 --- a/patches/0014-openroad-ram-reset.patch +++ b/patches/0014-openroad-ram-reset.patch @@ -20,7 +20,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index c73f269d6c..7fbfe970a5 100644 +index 6702d6699a..d9f544454f 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -45,6 +45,7 @@ generate_ram [-mask_size bits] @@ -415,10 +415,10 @@ index 7362a35c8e..a6481b09fd 100644 read_port_logic); diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 5f765b215b..9ccfcf5790 100644 +index 35f5bf3157..d24bbf4966 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -44,7 +44,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -43,7 +43,8 @@ generate_ram_netlist_cmd(int mask_size, const char* tapcell_name, const int max_tap_dist, const char* read_style, @@ -428,7 +428,7 @@ index 5f765b215b..9ccfcf5790 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -96,7 +97,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -95,7 +96,8 @@ generate_ram_netlist_cmd(int mask_size, ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, @@ -437,9 +437,9 @@ index 5f765b215b..9ccfcf5790 100644 + reset_value); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 998f61fde5..6d41e0bda8 100644 +index 2494d4c873..89ff8eb8f1 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -9,7 +9,9 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -499,7 +499,7 @@ index 998f61fde5..6d41e0bda8 100644 lappend ram_netlist_args -inv_cell $keys(-inv_cell) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index 0bd0331ed9..b964c56b3b 100644 +index 1192665493..522282eae9 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -510,7 +510,7 @@ index 0bd0331ed9..b964c56b3b 100644 "make_8x8_2r1w_zero_asap7", "make_8x8_2r1w_and_or_asap7", "make_7x7_1r2w_nangate45", -@@ -98,6 +99,11 @@ filegroup( +@@ -59,6 +60,11 @@ filegroup( "//test:asap7_nldm_data", "make_8x8_2r1w_zero_asap7_behavioral.vok", ], diff --git a/patches/0015-openroad-ram-banks.patch b/patches/0015-openroad-ram-banks.patch index 3ca71b0c2..324268533 100644 --- a/patches/0015-openroad-ram-banks.patch +++ b/patches/0015-openroad-ram-banks.patch @@ -22,7 +22,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 7fbfe970a5..8fabb35c70 100644 +index d9f544454f..caca31e8b5 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -46,6 +46,9 @@ generate_ram [-mask_size bits] @@ -745,10 +745,10 @@ index a6481b09fd..43a2724490 100644 if (filler_spacing > 0) { int filler_count = 0; diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 9ccfcf5790..d5eb7723c5 100644 +index d24bbf4966..cafbfcad18 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -45,7 +45,10 @@ generate_ram_netlist_cmd(int mask_size, +@@ -44,7 +44,10 @@ generate_ram_netlist_cmd(int mask_size, const int max_tap_dist, const char* read_style, const int zero_word, @@ -760,7 +760,7 @@ index 9ccfcf5790..d5eb7723c5 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -98,7 +101,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -97,7 +100,7 @@ generate_ram_netlist_cmd(int mask_size, ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, tapcell, max_tap_dist, read_style, zero_word, @@ -768,9 +768,9 @@ index 9ccfcf5790..d5eb7723c5 100644 + reset_value, banks, bank_columns, bank_order); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 6d41e0bda8..315a3d88bd 100644 +index 89ff8eb8f1..6e404175da 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -10,8 +10,14 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -851,7 +851,7 @@ index 6d41e0bda8..315a3d88bd 100644 lappend ram_netlist_args -inv_cell $keys(-inv_cell) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index b964c56b3b..fdb75124a0 100644 +index 522282eae9..b882508c0c 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -862,7 +862,7 @@ index b964c56b3b..fdb75124a0 100644 "make_8x8_2r1w_reset_asap7", "make_8x8_2r1w_zero_asap7", "make_8x8_2r1w_and_or_asap7", -@@ -104,6 +105,11 @@ filegroup( +@@ -65,6 +66,11 @@ filegroup( "//test:asap7_nldm_data", "make_8x8_2r1w_reset_asap7_behavioral.vok", ], diff --git a/patches/0016-openroad-ram-banked-read-ports.patch b/patches/0016-openroad-ram-banked-read-ports.patch index 297c11b06..c1c50e58b 100644 --- a/patches/0016-openroad-ram-banked-read-ports.patch +++ b/patches/0016-openroad-ram-banked-read-ports.patch @@ -14,7 +14,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 8fabb35c70..5f4dcdaa51 100644 +index caca31e8b5..a6fbf28bc9 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -49,6 +49,7 @@ generate_ram [-mask_size bits] @@ -357,10 +357,10 @@ index 43a2724490..9d75d28322 100644 std::string port_name = (r_total == 1) ? "Q" : fmt::format("Q{}", i); std::string addr_name; diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index d5eb7723c5..037e28f5ff 100644 +index cafbfcad18..5df5f55134 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -48,7 +48,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -47,7 +47,8 @@ generate_ram_netlist_cmd(int mask_size, const char* reset_value, const int banks, const int bank_columns, @@ -370,7 +370,7 @@ index d5eb7723c5..037e28f5ff 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -101,7 +102,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -100,7 +101,7 @@ generate_ram_netlist_cmd(int mask_size, ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, tapcell, max_tap_dist, read_style, zero_word, @@ -378,9 +378,9 @@ index d5eb7723c5..037e28f5ff 100644 + reset_value, banks, bank_columns, bank_order, rb_ports); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 315a3d88bd..3466fe562c 100644 +index 6e404175da..9c541fc52f 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -13,11 +13,13 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -456,7 +456,7 @@ index 315a3d88bd..3466fe562c 100644 lappend ram_netlist_args $key $keys($key) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index fdb75124a0..cd2a6d7cdb 100644 +index b882508c0c..218e3bff6b 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -467,7 +467,7 @@ index fdb75124a0..cd2a6d7cdb 100644 "make_8x8_2r1w_banks_asap7", "make_8x8_2r1w_reset_asap7", "make_8x8_2r1w_zero_asap7", -@@ -110,6 +111,11 @@ filegroup( +@@ -71,6 +72,11 @@ filegroup( "//test:asap7_nldm_data", "make_8x8_2r1w_banks_asap7_behavioral.vok", ], diff --git a/patches/0017-openroad-ram-read-latency.patch b/patches/0017-openroad-ram-read-latency.patch index 6d406b39d..53542bec2 100644 --- a/patches/0017-openroad-ram-read-latency.patch +++ b/patches/0017-openroad-ram-read-latency.patch @@ -15,7 +15,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 5f4dcdaa51..9b6f2bbc35 100644 +index a6fbf28bc9..28950270a6 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -50,6 +50,7 @@ generate_ram [-mask_size bits] @@ -299,10 +299,10 @@ index 9d75d28322..d5521b13ab 100644 // cycle, the last one's data is kept. std::string data_declarations; diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 037e28f5ff..4494870fdb 100644 +index 5df5f55134..f5b0df9f45 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -49,7 +49,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -48,7 +48,8 @@ generate_ram_netlist_cmd(int mask_size, const int banks, const int bank_columns, const char* bank_order, @@ -312,7 +312,7 @@ index 037e28f5ff..4494870fdb 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -102,7 +103,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -101,7 +102,8 @@ generate_ram_netlist_cmd(int mask_size, ram_gen->generate(mask_size, word_size, num_words, rw_ports, r_ports, w_ports, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, tapcell, max_tap_dist, read_style, zero_word, @@ -321,9 +321,9 @@ index 037e28f5ff..4494870fdb 100644 + read_latency); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 3466fe562c..75d6fbb387 100644 +index 9c541fc52f..1be985d19b 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -14,12 +14,14 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -391,7 +391,7 @@ index 3466fe562c..75d6fbb387 100644 lappend ram_netlist_args $key $keys($key) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index cd2a6d7cdb..83fa973277 100644 +index 218e3bff6b..f76c0a994a 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -402,7 +402,7 @@ index cd2a6d7cdb..83fa973277 100644 "make_8x8_rb_asap7", "make_8x8_2r1w_banks_asap7", "make_8x8_2r1w_reset_asap7", -@@ -116,6 +117,11 @@ filegroup( +@@ -77,6 +78,11 @@ filegroup( "//test:asap7_nldm_data", "make_8x8_rb_asap7_behavioral.vok", ], diff --git a/patches/0018-openroad-ram-write-mux.patch b/patches/0018-openroad-ram-write-mux.patch index b3e94976e..0e7fe50d3 100644 --- a/patches/0018-openroad-ram-write-mux.patch +++ b/patches/0018-openroad-ram-write-mux.patch @@ -15,7 +15,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 9b6f2bbc35..3f6215e900 100644 +index 28950270a6..d00ea4266f 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -51,6 +51,7 @@ generate_ram [-mask_size bits] @@ -258,10 +258,10 @@ index d5521b13ab..728cf882bf 100644 if (read_latency_ != 1) { logger_->error(RAM, 71, "-read_latency is 0 or 1."); diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 4494870fdb..57351d4216 100644 +index f5b0df9f45..eb39047776 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -50,7 +50,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -49,7 +49,8 @@ generate_ram_netlist_cmd(int mask_size, const int bank_columns, const char* bank_order, const int rb_ports, @@ -271,7 +271,7 @@ index 4494870fdb..57351d4216 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -104,7 +105,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -103,7 +104,7 @@ generate_ram_netlist_cmd(int mask_size, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, tapcell, max_tap_dist, read_style, zero_word, reset_value, banks, bank_columns, bank_order, rb_ports, @@ -279,9 +279,9 @@ index 4494870fdb..57351d4216 100644 + read_latency, write_style); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 75d6fbb387..309cad8d03 100644 +index 1be985d19b..7206ca848b 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -15,6 +15,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -354,7 +354,7 @@ index 75d6fbb387..309cad8d03 100644 lappend ram_netlist_args $key $keys($key) } diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index 83fa973277..604b8fa6be 100644 +index f76c0a994a..a7d89256e0 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -365,7 +365,7 @@ index 83fa973277..604b8fa6be 100644 "make_8x8_rb_latency_asap7", "make_8x8_rb_asap7", "make_8x8_2r1w_banks_asap7", -@@ -122,6 +123,11 @@ filegroup( +@@ -83,6 +84,11 @@ filegroup( "//test:asap7_nldm_data", "make_8x8_rb_latency_asap7_behavioral.vok", ], diff --git a/patches/0019-openroad-ram-periphery-unplaced.patch b/patches/0019-openroad-ram-periphery-unplaced.patch index 4dc5922a8..35e98b006 100644 --- a/patches/0019-openroad-ram-periphery-unplaced.patch +++ b/patches/0019-openroad-ram-periphery-unplaced.patch @@ -18,7 +18,7 @@ The ninth of the generate_regfile features carried onto generate_ram --- diff --git a/src/ram/README.md b/src/ram/README.md -index 3f6215e900..918957177a 100644 +index d00ea4266f..9203ca0651 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -84,6 +84,7 @@ generate_ram [-mask_size bits] @@ -324,10 +324,10 @@ index 728cf882bf..4cdfe57e2c 100644 { behavioral_verilog_filename_ = filename; diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 57351d4216..1d62729854 100644 +index eb39047776..5c34560b47 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -51,7 +51,9 @@ generate_ram_netlist_cmd(int mask_size, +@@ -50,7 +50,9 @@ generate_ram_netlist_cmd(int mask_size, const char* bank_order, const int rb_ports, const int read_latency, @@ -338,7 +338,7 @@ index 57351d4216..1d62729854 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -105,7 +107,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -104,7 +106,7 @@ generate_ram_netlist_cmd(int mask_size, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, tapcell, max_tap_dist, read_style, zero_word, reset_value, banks, bank_columns, bank_order, rb_ports, @@ -346,9 +346,9 @@ index 57351d4216..1d62729854 100644 + read_latency, write_style, periphery, pin_layer); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 309cad8d03..7ae7eb7754 100644 +index 7206ca848b..e8e86010b3 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -24,6 +24,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -402,7 +402,7 @@ index 309cad8d03..7ae7eb7754 100644 sta::define_cmd_args "generate_ram" {[-mask_size bits] diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD -index 604b8fa6be..eab9e82099 100644 +index a7d89256e0..77f753c358 100644 --- a/src/ram/test/BUILD +++ b/src/ram/test/BUILD @@ -13,6 +13,7 @@ COMPULSORY_TESTS = [ @@ -413,7 +413,7 @@ index 604b8fa6be..eab9e82099 100644 "make_8x8_2r1w_mux_asap7", "make_8x8_rb_latency_asap7", "make_8x8_rb_asap7", -@@ -128,6 +129,11 @@ filegroup( +@@ -89,6 +90,11 @@ filegroup( "//test:asap7_nldm_data", "make_8x8_2r1w_mux_asap7_behavioral.vok", ], diff --git a/patches/0020-openroad-ram-cells-name.patch b/patches/0020-openroad-ram-cells-name.patch index 2ab9767a0..afa8cd521 100644 --- a/patches/0020-openroad-ram-cells-name.patch +++ b/patches/0020-openroad-ram-cells-name.patch @@ -18,7 +18,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index 918957177a..fde50b5ba1 100644 +index 9203ca0651..683015ddab 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -52,6 +52,8 @@ generate_ram [-mask_size bits] @@ -273,10 +273,10 @@ index 4cdfe57e2c..74d6985251 100644 int r_total = rw_ports + r_ports; const int num_write = rw_ports + w_ports; diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 1d62729854..b9b51b3a13 100644 +index 5c34560b47..bc76a2c750 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -53,7 +53,9 @@ generate_ram_netlist_cmd(int mask_size, +@@ -52,7 +52,9 @@ generate_ram_netlist_cmd(int mask_size, const int read_latency, const char* write_style, const char* periphery, @@ -287,7 +287,7 @@ index 1d62729854..b9b51b3a13 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -107,7 +109,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -106,7 +108,8 @@ generate_ram_netlist_cmd(int mask_size, column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, tapcell, max_tap_dist, read_style, zero_word, reset_value, banks, bank_columns, bank_order, rb_ports, @@ -296,9 +296,9 @@ index 1d62729854..b9b51b3a13 100644 + name); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 7ae7eb7754..8bafbdd5b6 100644 +index e8e86010b3..460941a99a 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -16,6 +16,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] diff --git a/patches/0021-openroad-ram-word-decoder.patch b/patches/0021-openroad-ram-word-decoder.patch index 26f2b3912..fd3281170 100644 --- a/patches/0021-openroad-ram-word-decoder.patch +++ b/patches/0021-openroad-ram-word-decoder.patch @@ -12,7 +12,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/README.md b/src/ram/README.md -index fde50b5ba1..abbbca09f7 100644 +index 683015ddab..4e17cb1167 100644 --- a/src/ram/README.md +++ b/src/ram/README.md @@ -54,6 +54,7 @@ generate_ram [-mask_size bits] @@ -68,10 +68,10 @@ index 74d6985251..b5a03e9315 100644 bank_columns_ = std::max(bank_columns, 1); bank_interleaved_ = bank_order == "interleaved"; diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index b9b51b3a13..6fdfcf5eda 100644 +index bc76a2c750..41f4ec7c5c 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -55,7 +55,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -54,7 +54,8 @@ generate_ram_netlist_cmd(int mask_size, const char* periphery, const char* pin_layer, const char* cells, @@ -81,7 +81,7 @@ index b9b51b3a13..6fdfcf5eda 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -110,7 +111,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -109,7 +110,7 @@ generate_ram_netlist_cmd(int mask_size, tapcell, max_tap_dist, read_style, zero_word, reset_value, banks, bank_columns, bank_order, rb_ports, read_latency, write_style, periphery, pin_layer, cells, @@ -89,9 +89,9 @@ index b9b51b3a13..6fdfcf5eda 100644 + name, decoder); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 8bafbdd5b6..1b056eaabf 100644 +index 460941a99a..8efed6fdfd 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -18,6 +18,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] diff --git a/patches/0022-openroad-ram-bit-folds.patch b/patches/0022-openroad-ram-bit-folds.patch index 63b1dd7fd..ef9e0fac2 100644 --- a/patches/0022-openroad-ram-bit-folds.patch +++ b/patches/0022-openroad-ram-bit-folds.patch @@ -1,8 +1,10 @@ From: =?UTF-8?q?=C3=98yvind=20Harboe?= Subject: [PATCH] ram: generate_ram -bit_folds, a word's slices in rows --bit_folds k lays a word's mask slices (-mask_size word/k) in k rows -instead of side by side. generate_ram puts a word in one row, a bit's +-bit_folds k lays a word's mask slices (-mask_size, word/k rounded up) +in k rows instead of side by side; where k does not divide the word the +last fold is short, its missing bits empty columns (XiangShan's +FtqMetaQueueRedirect, 211 bits in 4 folds). generate_ram puts a word in one row, a bit's cells side by side, so a wide word with many ports is a long thin array: XiangShan's integer register file, 64 bits, 12 read and 9 write ports, came out 1458 x 31 um. With folds the decoder, select-buffer and @@ -19,7 +21,7 @@ see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h -index d253b23818..5400b8b04a 100644 +index d253b23818..4b82175c0d 100644 --- a/src/ram/include/ram/ram.h +++ b/src/ram/include/ram/ram.h @@ -123,7 +123,8 @@ class RamGen @@ -32,7 +34,7 @@ index d253b23818..5400b8b04a 100644 void ramPdngen(const char* power_net_name, const char* ground_net_name, -@@ -385,6 +386,28 @@ class RamGen +@@ -385,6 +386,29 @@ class RamGen // a row; each pin where its connections land, on pin_layer_'s tracks bool periphery_unplaced_{false}; std::string ram_name_; // the block's and the behavioral model's name @@ -40,6 +42,7 @@ index d253b23818..5400b8b04a 100644 + // so a wide word with many ports is as tall as it is wide; every + // column is k rows a word + int bit_folds_{1}; ++ int word_bits_{0}; // the word's bits, short of the folds' pads + int slice_width_{0}; // a slice's columns: its bits, and its select + // with -bit_folds a word is written whole: its write logic (enables, + // priority, hold, clock gate, reset tie, select inverters) built in its @@ -62,7 +65,7 @@ index d253b23818..5400b8b04a 100644 bool marking_periphery_{false}; Cell* periphery_cell_{nullptr}; diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp -index b5a03e9315..cf48730c73 100644 +index b5a03e9315..a49a3612cb 100644 --- a/src/ram/src/ram.cpp +++ b/src/ram/src/ram.cpp @@ -349,18 +349,25 @@ void RamGen::makeSlice(const int slice_idx, @@ -136,7 +139,7 @@ index b5a03e9315..cf48730c73 100644 vector we(num_write); for (int w = 0; w < num_write; ++w) { we[w] = makeNet(prefix, fmt::format("we{}", w)); -@@ -490,6 +501,10 @@ void RamGen::makeSlice(const int slice_idx, +@@ -490,7 +501,18 @@ void RamGen::makeSlice(const int slice_idx, } } @@ -145,9 +148,17 @@ index b5a03e9315..cf48730c73 100644 + } + for (int local_bit = 0; local_bit < mask_size; ++local_bit) { ++ if (start_bit_idx + local_bit >= word_bits_) { ++ // a short fold's pad: its column empty in this row ++ ram_grid_.addCell(nullptr, ++ sliceOffset(slice_idx) ++ + local_bit * column_mux_ratio + word_idx); ++ continue; ++ } auto name = fmt::format("{}.bit{}", prefix, start_bit_idx + local_bit); vector outs(r_total); -@@ -606,13 +621,13 @@ void RamGen::makeSlice(const int slice_idx, + for (int r_port = 0; r_port < r_total; ++r_port) { +@@ -606,13 +628,13 @@ void RamGen::makeSlice(const int slice_idx, } } @@ -163,7 +174,7 @@ index b5a03e9315..cf48730c73 100644 makeInst(sel_cell.get(), prefix, "cg", -@@ -640,7 +655,7 @@ void RamGen::makeSlice(const int slice_idx, +@@ -640,7 +662,7 @@ void RamGen::makeSlice(const int slice_idx, // Make clock and // this AND gate needs to be fed a net created by a decoder // adding any net will automatically connect with any port @@ -172,7 +183,7 @@ index b5a03e9315..cf48730c73 100644 makeInst(sel_cell.get(), prefix, "gcand", -@@ -651,7 +666,7 @@ void RamGen::makeSlice(const int slice_idx, +@@ -651,7 +673,7 @@ void RamGen::makeSlice(const int slice_idx, } // Make select inverters @@ -181,7 +192,7 @@ index b5a03e9315..cf48730c73 100644 for (int i = 0; i < r_total; ++i) { if (selects[num_write + i] == nullptr) { continue; // a banked read port's other banks -@@ -665,9 +680,10 @@ void RamGen::makeSlice(const int slice_idx, +@@ -665,9 +687,10 @@ void RamGen::makeSlice(const int slice_idx, } } @@ -194,7 +205,7 @@ index b5a03e9315..cf48730c73 100644 } // Note: For column_mux_ratio > 1, creates one shared select_b net per row and -@@ -703,7 +719,8 @@ void RamGen::makeWord(const int slices_per_word, +@@ -703,7 +726,8 @@ void RamGen::makeWord(const int slices_per_word, for (size_t w = 0; w < data_input.size(); ++w) { slice_inputs.emplace_back(data_input[w].begin() + start_idx, data_input[w].begin() + start_idx + mask_size); @@ -204,7 +215,7 @@ index b5a03e9315..cf48730c73 100644 } std::vector> slice_outputs; slice_outputs.reserve(r_total); -@@ -789,6 +806,9 @@ void RamGen::makeDecoderColumn( +@@ -789,6 +813,9 @@ void RamGen::makeDecoderColumn( } } decoder_layout->addCell(std::move(word_cell)); @@ -214,7 +225,7 @@ index b5a03e9315..cf48730c73 100644 } marking_periphery_ = false; ram_grid_.addLayout(std::move(decoder_layout)); -@@ -819,6 +839,9 @@ void RamGen::makeBufferColumn(const std::string& prefix, +@@ -819,6 +846,9 @@ void RamGen::makeBufferColumn(const std::string& prefix, {buffer_ports_[{PortRoleType::DataOut, 0}], select_nets[word]}}); } buffer_layout->addCell(std::move(buf_cell)); @@ -224,7 +235,7 @@ index b5a03e9315..cf48730c73 100644 } marking_periphery_ = false; ram_grid_.addLayout(std::move(buffer_layout)); -@@ -876,6 +899,9 @@ void RamGen::makeWordDecoderColumn( +@@ -876,6 +906,9 @@ void RamGen::makeWordDecoderColumn( } } decoder_layout->addCell(std::move(row_cell)); @@ -234,7 +245,16 @@ index b5a03e9315..cf48730c73 100644 } marking_periphery_ = false; ram_grid_.addLayout(std::move(decoder_layout)); -@@ -1916,7 +1942,8 @@ void RamGen::generate(const int mask_size, +@@ -1891,7 +1924,7 @@ void RamGen::ramRouting(int thread_count) + } + + void RamGen::generate(const int mask_size, +- const int word_size, ++ const int word_bits, + const int num_words, + const int rw_ports, + const int r_ports, +@@ -1916,7 +1949,8 @@ void RamGen::generate(const int mask_size, const std::string& pin_layer, const std::string& cells, const std::string& name, @@ -244,19 +264,31 @@ index b5a03e9315..cf48730c73 100644 { // Banks: every port decodes every word's whole address, and a row holds // bank_columns words, laid out as the column mux lays out its words; -@@ -1980,6 +2007,23 @@ void RamGen::generate(const int mask_size, +@@ -1980,13 +2014,42 @@ void RamGen::generate(const int mask_size, // the words in a row: the column mux's, or the banks side by side const int column_mux_ratio = banked_ ? bank_columns_ : column_mux_ratio_arg; words_per_row_ = column_mux_ratio; + bit_folds_ = std::max(bit_folds, 1); + slice_width_ = mask_size * column_mux_ratio + column_mux_ratio; ++ // the word's own bits; with -bit_folds the last fold may be short, its ++ // missing bits pads: columns with no port, flop or read tree ++ word_bits_ = word_bits; ++ const int word_size = bit_folds_ > 1 ? mask_size * bit_folds_ : word_bits; + if (bit_folds_ > 1) { -+ if (word_size / mask_size != bit_folds_) { ++ const int fold = (word_bits + bit_folds_ - 1) / bit_folds_; ++ if (mask_size != fold) { + logger_->error(RAM, + 83, + "-bit_folds {} needs -mask_size {}: a fold is a slice.", + bit_folds_, -+ word_size / bit_folds_); ++ fold); ++ } ++ if (word_size - word_bits >= mask_size) { ++ logger_->error(RAM, ++ 88, ++ "-bit_folds {} leaves a fold of -word_size {} empty.", ++ bit_folds_, ++ word_bits); + } + if (use_latch || (!banked_ && column_mux_ratio > 1)) { + logger_->error(RAM, @@ -268,7 +300,15 @@ index b5a03e9315..cf48730c73 100644 if (num_words / column_mux_ratio == 1) { logger_->error(RAM, 42, "1-row RAMs are not supported."); } -@@ -2039,6 +2083,7 @@ void RamGen::generate(const int mask_size, + const int slices_per_word = word_size / mask_size; + // the block's name: -name, or RAMx + const std::string ram_name +- = name.empty() ? fmt::format("RAM{}x{}", num_words, word_size) : name; ++ = name.empty() ? fmt::format("RAM{}x{}", num_words, word_bits) : name; + ram_name_ = ram_name; + + // error checking for column_mux_ratio +@@ -2039,6 +2102,7 @@ void RamGen::generate(const int mask_size, storage_inverted_ = false; storage_nets_.clear(); tree_nodes_.clear(); @@ -276,7 +316,7 @@ index b5a03e9315..cf48730c73 100644 storage_cell_ = storage_cell; tristate_cell_ = tristate_cell; inv_cell_ = inv_cell; -@@ -2208,7 +2253,8 @@ void RamGen::generate(const int mask_size, +@@ -2208,7 +2272,8 @@ void RamGen::generate(const int mask_size, // mux layout columns + per-port buffer/decoder columns + inverter columns int col_cell_count @@ -286,7 +326,7 @@ index b5a03e9315..cf48730c73 100644 ram_grid_.setNumLayouts(col_cell_count); auto clock = makeBTerm("clk", dbIoType::INPUT); -@@ -2231,7 +2277,9 @@ void RamGen::generate(const int mask_size, +@@ -2231,7 +2296,9 @@ void RamGen::generate(const int mask_size, num_write, vector(slices_per_word, nullptr)); for (int w = 0; w < num_write; ++w) { const std::string we = num_write == 1 ? "we" : fmt::format("we{}", w); @@ -297,7 +337,53 @@ index b5a03e9315..cf48730c73 100644 write_enable[w][slice] = makeBTerm(fmt::format("{}[{}]", we, slice), dbIoType::INPUT); } -@@ -2763,10 +2811,19 @@ void RamGen::generate(const int mask_size, +@@ -2398,6 +2465,16 @@ void RamGen::generate(const int mask_size, + vector> data_inputs(num_write); + vector> D_nets(num_write, vector(word_size)); + for (int bit = 0; bit < word_size; ++bit) { ++ if (bit >= word_bits_) { ++ // a short fold's pad: no ports ++ for (int w = 0; w < num_write; ++w) { ++ data_inputs[w].push_back(nullptr); ++ } ++ for (auto& q : q_outputs_) { ++ q.push_back(nullptr); ++ } ++ continue; ++ } + for (int w = 0; w < num_write; ++w) { + const std::string d = num_write == 1 ? "D" : fmt::format("D{}", w); + data_inputs[w].push_back( +@@ -2440,7 +2517,9 @@ void RamGen::generate(const int mask_size, + for (int w = 0; w < column_mux_ratio; ++w) { + for (int port = 0; port < r_total; ++port) { + for (int bit = 0; bit < word_size; ++bit) { +- word_q_nets[w][port][bit] = q_outputs_[port][bit]->getNet(); ++ word_q_nets[w][port][bit] = q_outputs_[port][bit] ++ ? q_outputs_[port][bit]->getNet() ++ : nullptr; + } + } + } +@@ -2503,7 +2582,7 @@ void RamGen::generate(const int mask_size, + if (wordAt(row, w) == zero_word_) { + continue; + } +- for (int bit = 0; bit < word_size; ++bit) { ++ for (int bit = 0; bit < word_bits_; ++bit) { + const std::string prefix = fmt::format( + "storage_{}_{}_{}", row, w, (bit / mask_size) * mask_size); + storage_nets_[{row, w, bit}] = makeNet( +@@ -2537,7 +2616,7 @@ void RamGen::generate(const int mask_size, + const vector terms = terms_of(port, w); + const int n = static_cast(terms.size()); + const bool flip = treeInverted(0, n) != storage_inverted_; +- for (int bit = 0; bit < word_size; ++bit) { ++ for (int bit = 0; bit < word_bits_; ++bit) { + const std::string prefix + = banked_ ? fmt::format("read_p{}_b{}", port, bit) + : fmt::format("read_w{}_p{}_b{}", w, port, bit); +@@ -2763,10 +2842,22 @@ void RamGen::generate(const int mask_size, } } @@ -312,13 +398,16 @@ index b5a03e9315..cf48730c73 100644 + int buf_col = sliceOffset(slice) + bit * column_mux_ratio; + auto& buffer_grid_cell + = buffer_cells[{buf_col, bit_folds_ > 1 ? slice : 0}]; ++ if (bit_idx >= word_bits_) { ++ continue; // a short fold's pad: an empty cell ++ } + if (!buffer_grid_cell) { + buffer_grid_cell = std::make_unique(); + } marking_periphery_ = true; // the input buffers for (int w = 0; w < num_write; ++w) { makeInst(buffer_grid_cell.get(), -@@ -2779,11 +2836,11 @@ void RamGen::generate(const int mask_size, +@@ -2779,11 +2870,11 @@ void RamGen::generate(const int mask_size, D_nets[w][bit_idx]}}); } marking_periphery_ = false; @@ -333,7 +422,7 @@ index b5a03e9315..cf48730c73 100644 // indices for creating buffers int r_buf_idx = 0; -@@ -2834,7 +2891,7 @@ void RamGen::generate(const int mask_size, +@@ -2834,7 +2925,7 @@ void RamGen::generate(const int mask_size, for (int col = 0; col < inv_col_count; ++col) { int start_port = col * ports_per_col; int end_port = std::min(start_port + ports_per_col, total_ports); @@ -342,7 +431,7 @@ index b5a03e9315..cf48730c73 100644 num_row_bits, start_port, end_port, -@@ -2933,7 +2990,9 @@ void RamGen::generate(const int mask_size, +@@ -2933,7 +3024,9 @@ void RamGen::generate(const int mask_size, } // // One extra row at the top for placing input buffers, one extra row for // // negative latches if use latch-based ram @@ -353,7 +442,7 @@ index b5a03e9315..cf48730c73 100644 // auto cell_inv_layout = std::make_unique(odb::vertical); // // check for AND gate, specific case for 2 words -@@ -3042,9 +3101,10 @@ void RamGen::generate(const int mask_size, +@@ -3042,9 +3135,10 @@ void RamGen::generate(const int mask_size, unplacePeriphery(); } @@ -362,15 +451,15 @@ index b5a03e9315..cf48730c73 100644 - slices_per_word, - mask_size, + bit_folds_ > 1 ? 1 : slices_per_word, -+ bit_folds_ > 1 ? word_size : mask_size, ++ bit_folds_ > 1 ? word_bits_ : mask_size, num_words, rw_ports, r_ports, diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 6fdfcf5eda..4aaa60f0f3 100644 +index 41f4ec7c5c..78d76a9488 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -56,7 +56,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -55,7 +55,8 @@ generate_ram_netlist_cmd(int mask_size, const char* pin_layer, const char* cells, const char* name, @@ -380,7 +469,7 @@ index 6fdfcf5eda..4aaa60f0f3 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -111,7 +112,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -110,7 +111,7 @@ generate_ram_netlist_cmd(int mask_size, tapcell, max_tap_dist, read_style, zero_word, reset_value, banks, bank_columns, bank_order, rb_ports, read_latency, write_style, periphery, pin_layer, cells, @@ -388,9 +477,9 @@ index 6fdfcf5eda..4aaa60f0f3 100644 + name, decoder, bit_folds); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index 1b056eaabf..db7e1d06c8 100644 +index 8efed6fdfd..8e7ef1167c 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -19,6 +19,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -418,7 +507,18 @@ index 1b056eaabf..db7e1d06c8 100644 set column_mux_ratio 1 if { [info exists keys(-column_mux_ratio)] } { -@@ -221,6 +223,11 @@ proc generate_ram_netlist { args } { +@@ -65,7 +67,9 @@ proc generate_ram_netlist { args } { + set mask_size $word_size + } + +- if { $word_size % $mask_size != 0 } { ++ # with -bit_folds the last fold may be short ++ set folded [expr { [info exists keys(-bit_folds)] && $keys(-bit_folds) > 1 }] ++ if { $word_size % $mask_size != 0 && !$folded } { + utl::error RAM 26 "The -word_size ($word_size) must be divisible by -mask_size ($mask_size)." + } + +@@ -221,6 +225,11 @@ proc generate_ram_netlist { args } { # The address decoders: row, a decoder per row (an AND2 chain), the # column mux selecting within it; or word, a balanced AND2 tree over # each word's whole address. @@ -430,7 +530,7 @@ index 1b056eaabf..db7e1d06c8 100644 set decoder row if { [info exists keys(-decoder)] } { set decoder $keys(-decoder) -@@ -262,7 +269,7 @@ proc generate_ram_netlist { args } { +@@ -262,7 +271,7 @@ proc generate_ram_netlist { args } { $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name \ @@ -439,7 +539,7 @@ index 1b056eaabf..db7e1d06c8 100644 } sta::define_cmd_args "generate_ram" {[-mask_size bits] -@@ -298,7 +305,7 @@ proc generate_ram { args } { +@@ -298,7 +307,7 @@ proc generate_ram { args } { -hor_layer -filler_cells -tapcell -max_tap_dist -write_behavioral_verilog -read_style -zero_word -reset_value -banks -bank_columns -bank_order -rb_ports -read_latency -write_style @@ -448,7 +548,7 @@ index 1b056eaabf..db7e1d06c8 100644 sta::check_argc_eq0 "generate_ram" $args -@@ -348,7 +355,7 @@ proc generate_ram { args } { +@@ -348,7 +357,7 @@ proc generate_ram { args } { } foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style diff --git a/patches/0023-openroad-ram-periphery-verilog.patch b/patches/0023-openroad-ram-periphery-verilog.patch index 720a461f7..3dd1f34f3 100644 --- a/patches/0023-openroad-ram-periphery-verilog.patch +++ b/patches/0023-openroad-ram-periphery-verilog.patch @@ -16,7 +16,7 @@ generate_ram; see OpenROAD #11669. Not upstreamed. --- diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h -index 5400b8b04a..2d9b7181d2 100644 +index 4b82175c0d..1cafb2c0b2 100644 --- a/src/ram/include/ram/ram.h +++ b/src/ram/include/ram/ram.h @@ -124,7 +124,8 @@ class RamGen @@ -29,7 +29,7 @@ index 5400b8b04a..2d9b7181d2 100644 void ramPdngen(const char* power_net_name, const char* ground_net_name, -@@ -413,6 +414,15 @@ class RamGen +@@ -414,6 +415,15 @@ class RamGen Cell* periphery_cell_{nullptr}; std::vector periphery_insts_; void unplacePeriphery(); @@ -46,7 +46,7 @@ index 5400b8b04a..2d9b7181d2 100644 std::string addr_flop_d_, addr_flop_clk_, addr_flop_q_; bool addr_flop_inverted_{false}; diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp -index cf48730c73..7b670b6da9 100644 +index a49a3612cb..a56b944946 100644 --- a/src/ram/src/ram.cpp +++ b/src/ram/src/ram.cpp @@ -13,6 +13,7 @@ @@ -57,7 +57,7 @@ index cf48730c73..7b670b6da9 100644 #include #include #include -@@ -1943,7 +1944,8 @@ void RamGen::generate(const int mask_size, +@@ -1950,7 +1951,8 @@ void RamGen::generate(const int mask_size, const std::string& cells, const std::string& name, const std::string& decoder, @@ -67,7 +67,7 @@ index cf48730c73..7b670b6da9 100644 { // Banks: every port decodes every word's whole address, and a row holds // bank_columns words, laid out as the column mux lays out its words; -@@ -1976,7 +1978,13 @@ void RamGen::generate(const int mask_size, +@@ -1983,7 +1985,13 @@ void RamGen::generate(const int mask_size, rb_ports_ = rb_ports; read_latency_ = read_latency; write_mux_ = write_style == "mux"; @@ -82,7 +82,7 @@ index cf48730c73..7b670b6da9 100644 pin_layer_ = pin_layer; periphery_insts_.clear(); marking_periphery_ = false; -@@ -2231,7 +2239,10 @@ void RamGen::generate(const int mask_size, +@@ -2250,7 +2258,10 @@ void RamGen::generate(const int mask_size, block_ = chip->getBlock(); if (!block_) { @@ -94,7 +94,7 @@ index cf48730c73..7b670b6da9 100644 } // One column per bit plus one select/control column per slice, -@@ -3118,8 +3129,235 @@ void RamGen::generate(const int mask_size, +@@ -3152,8 +3163,235 @@ void RamGen::generate(const int mask_size, // (those of the periphery too, while they are still placed), on the pin // layer's track grid inside the outline: these pins are for a macro // placer to orient the core by, never routed. @@ -331,10 +331,10 @@ index cf48730c73..7b670b6da9 100644 = db_->getTech()->findLayer(pin_layer_.c_str()); if (layer == nullptr) { diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i -index 4aaa60f0f3..d70a2aecda 100644 +index 78d76a9488..0040503bfd 100644 --- a/src/ram/src/ram.i +++ b/src/ram/src/ram.i -@@ -57,7 +57,8 @@ generate_ram_netlist_cmd(int mask_size, +@@ -56,7 +56,8 @@ generate_ram_netlist_cmd(int mask_size, const char* cells, const char* name, const char* decoder, @@ -344,7 +344,7 @@ index 4aaa60f0f3..d70a2aecda 100644 { RamGen* ram_gen = ord::getRamGen(); odb::dbDatabase* db = ord::getDb(); -@@ -112,7 +113,7 @@ generate_ram_netlist_cmd(int mask_size, +@@ -111,7 +112,7 @@ generate_ram_netlist_cmd(int mask_size, tapcell, max_tap_dist, read_style, zero_word, reset_value, banks, bank_columns, bank_order, rb_ports, read_latency, write_style, periphery, pin_layer, cells, @@ -352,9 +352,9 @@ index 4aaa60f0f3..d70a2aecda 100644 + name, decoder, bit_folds, wrapper_verilog); } - void generate_regfile_cmd(const char* spec_path, + void ram_pdngen(const char* power_net_name, const char* ground_net_name, diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl -index db7e1d06c8..19b99d4205 100644 +index 8e7ef1167c..0797431e65 100644 --- a/src/ram/src/ram.tcl +++ b/src/ram/src/ram.tcl @@ -28,7 +28,8 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] @@ -376,7 +376,7 @@ index db7e1d06c8..19b99d4205 100644 set column_mux_ratio 1 if { [info exists keys(-column_mux_ratio)] } { -@@ -200,10 +201,14 @@ proc generate_ram_netlist { args } { +@@ -202,10 +203,14 @@ proc generate_ram_netlist { args } { set periphery placed if { [info exists keys(-periphery)] } { set periphery $keys(-periphery) @@ -393,7 +393,7 @@ index db7e1d06c8..19b99d4205 100644 set pin_layer "" if { [info exists keys(-pin_layer)] } { set pin_layer $keys(-pin_layer) -@@ -269,7 +274,7 @@ proc generate_ram_netlist { args } { +@@ -271,7 +276,7 @@ proc generate_ram_netlist { args } { $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name \ diff --git a/patches/0024-openroad-ram-write-priority-or.patch b/patches/0024-openroad-ram-write-priority-or.patch new file mode 100644 index 000000000..ad7fe1627 --- /dev/null +++ b/patches/0024-openroad-ram-write-priority-or.patch @@ -0,0 +1,1639 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -write_priority or, colliding writes OR'd + +-write_priority says what a word takes when two write ports write it in +one cycle: last, the last port's data, as before; or or, the OR of every +writing port's data. firtool's register files (XiangShan's IntRegFile, +FpRegFile, VfRegFile) merge their writes with an OR, so a generated +register file in their place is equivalent to the RTL only with or; it +also drops each word's priority logic, an inverter and an AND2 per port +but the last. The behavioral model follows the option. + +The fourteenth of the generate_regfile features carried onto +generate_ram (generate_regfile's default); see OpenROAD #11669. Not +upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 4e17cb1167..1ab0b488f4 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -52,6 +52,7 @@ generate_ram [-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] ++ [-write_priority last|or] + [-cells {role master ...}] + [-name name] + [-decoder row|word] +@@ -87,6 +88,7 @@ generate_ram [-mask_size bits] + | `-rb_ports` | Banked read ports, with `-banks`: each an address and a data output per bank (`addr_rb_b`, `Qrb_b`), the address the word's index in its bank, every bank read independently. Default: 0. | + | `-read_latency` | `1` registers every read port's address, a plain positive-edge flop per address bit, so the data follows a cycle after the address. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. | + | `-write_style` | How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock. Not with `-use_latch`. Default: `clock_gate`. | ++| `-write_priority` | Where two write ports write the same word in one cycle: `last`, the last port's data; or `or`, the OR of every writing port's data, as RTL that merges its writes with an OR describes it (firtool's register files). `or` drops a word's priority logic, an inverter and an AND2 per port but the last. Default: `last`. | + | `-periphery`, `-pin_layer` | `generate_ram_netlist` only. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. Default: `placed`. | + | `-cells` | The cell for a role (`inv`, `and2`, `buffer`, `clock_gate`, `aoi22`, `ao22`, `or2`, `nand2`, `nor2`, `tie`, `addr_flop`), instead of the smallest the libraries have of its function. An AOI22 or AO22 given is checked by its truth table. Default: the smallest of each. | + | `-name` | The block's and the behavioral model's name. Default: `RAMx`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index 1cafb2c0b2..ffb19bcdd6 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -119,6 +119,7 @@ class RamGen + int rb_ports = 0, + int read_latency = 0, + const std::string& write_style = "clock_gate", ++ const std::string& write_priority = "last", + const std::string& periphery = "placed", + const std::string& pin_layer = "", + const std::string& cells = "", +@@ -381,6 +382,9 @@ class RamGen + // -write_style mux: no clock gate; each bit's flop on the clock, its D + // the new data where the word is written and its own value elsewhere + bool write_mux_{false}; ++ // -write_priority or: where ports write the same word in a cycle, the ++ // word takes the OR of their data, not the last port's ++ bool write_or_{false}; + // -periphery unplaced: the periphery (address inverters and registers, + // decoders, select buffers, each word's select cell, the input + // buffers) left for a parent to place; the outline the placed core and +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index a56b944946..950f185239 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -453,8 +453,9 @@ void RamGen::makeSlice(const int slice_idx, + // More than one write port: port w writes this word when its row select + // and its write enable are both high (we{w}), and its data is taken + // unless a later port writes the word in the same cycle (take{w}): the +- // last port wins, as in the behavioral model. The clock gate opens for +- // any of them. ++ // last port wins, as in the behavioral model. With -write_priority or ++ // every writing port's data is taken (take{w} is we{w}) and the word ++ // gets their OR. The clock gate opens for any of them. + vector take(num_write); + if (shared) { + take = word_write.take; +@@ -473,21 +474,25 @@ void RamGen::makeSlice(const int slice_idx, + take[num_write - 1] = we[num_write - 1]; + dbNet* later = we[num_write - 1]; + for (int w = num_write - 2; w >= 0; --w) { +- auto later_b = makeNet(prefix, fmt::format("later{}_b", w)); +- makeInst(sel_cell.get(), +- prefix, +- fmt::format("later_inv{}", w), +- inv_cell_, +- {{inv_ports_[{PortRoleType::DataIn, 0}], later}, +- {inv_ports_[{PortRoleType::DataOut, 0}], later_b}}); +- take[w] = makeNet(prefix, fmt::format("take{}", w)); +- makeInst(sel_cell.get(), +- prefix, +- fmt::format("take_and{}", w), +- and2_cell_, +- {{and2_ports_[{PortRoleType::DataIn, 0}], we[w]}, +- {and2_ports_[{PortRoleType::DataIn, 1}], later_b}, +- {and2_ports_[{PortRoleType::DataOut, 0}], take[w]}}); ++ if (write_or_) { ++ take[w] = we[w]; ++ } else { ++ auto later_b = makeNet(prefix, fmt::format("later{}_b", w)); ++ makeInst(sel_cell.get(), ++ prefix, ++ fmt::format("later_inv{}", w), ++ inv_cell_, ++ {{inv_ports_[{PortRoleType::DataIn, 0}], later}, ++ {inv_ports_[{PortRoleType::DataOut, 0}], later_b}}); ++ take[w] = makeNet(prefix, fmt::format("take{}", w)); ++ makeInst(sel_cell.get(), ++ prefix, ++ fmt::format("take_and{}", w), ++ and2_cell_, ++ {{and2_ports_[{PortRoleType::DataIn, 0}], we[w]}, ++ {and2_ports_[{PortRoleType::DataIn, 1}], later_b}, ++ {and2_ports_[{PortRoleType::DataOut, 0}], take[w]}}); ++ } + // any port from w on writes: the next earlier port's later, and at + // port 0 the clock gate's enable + auto any = w == 0 ? we_net : makeNet(prefix, fmt::format("later{}", w)); +@@ -1946,6 +1951,7 @@ void RamGen::generate(const int mask_size, + const int rb_ports, + const int read_latency, + const std::string& write_style, ++ const std::string& write_priority, + const std::string& periphery, + const std::string& pin_layer, + const std::string& cells, +@@ -1985,6 +1991,7 @@ void RamGen::generate(const int mask_size, + rb_ports_ = rb_ports; + read_latency_ = read_latency; + write_mux_ = write_style == "mux"; ++ write_or_ = write_priority == "or"; + periphery_verilog_ = periphery == "verilog"; + periphery_unplaced_ = periphery == "unplaced" || periphery_verilog_; + wrapper_verilog_ = wrapper_verilog; +@@ -3709,20 +3716,35 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + } + + // Write logic, the ports in order: where two write the same word in a +- // cycle, the last one's data is kept. ++ // cycle, the last one's data is kept. With -write_priority or each ++ // port also writes the data of every earlier port writing the same ++ // slice, so the last one writes the OR of them all. + std::string data_declarations; + std::string enable_declarations; + std::string write_logic; + for (int w = 0; w < num_write; ++w) { + const std::string write_addr + = rw_ports > 0 ? std::string("addr_rw") : wbus("addr_w", w); ++ std::string write_data ++ = fmt::format("{}[i*{} +:{}]", wbus("D", w), mask_size, mask_size); ++ for (int v = 0; write_or_ && v < w; ++v) { ++ write_data += fmt::format( ++ "\n | ({{{}{{{}[i] && {} == {}}}}} & {}[i*{} +:{}])", ++ mask_size, ++ wbus("we", v), ++ wbus("addr_w", v), ++ write_addr, ++ wbus("D", v), ++ mask_size, ++ mask_size); ++ } + data_declarations += fmt::format( + " input [{}:0] {};\n", word_size_bit - 1, wbus("D", w)); + enable_declarations += fmt::format( + " input [{}:0] {};\n", slices_per_word - 1, wbus("we", w)); + write_logic += fmt::format(R"( for (i = 0; i < {}; i = i + 1) begin + if ({}[i]{}) begin +- mem[{}][i*{} +:{}] <= {}[i*{} +:{}]; ++ mem[{}][i*{} +:{}] <= {}; + end + end + )", +@@ -3736,9 +3758,7 @@ void RamGen::writeBehavioralVerilog(const std::string& filename, + write_addr, + mask_size, + mask_size, +- wbus("D", w), +- mask_size, +- mask_size); ++ write_data); + } + + std::string reset_declaration; +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 0040503bfd..429ae8b763 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -51,6 +51,7 @@ generate_ram_netlist_cmd(int mask_size, + const int rb_ports, + const int read_latency, + const char* write_style, ++ const char* write_priority, + const char* periphery, + const char* pin_layer, + const char* cells, +@@ -111,7 +112,7 @@ generate_ram_netlist_cmd(int mask_size, + column_mux_ratio, use_latch, storage_cell, tristate_cell, inv_cell, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, +- read_latency, write_style, periphery, pin_layer, cells, ++ read_latency, write_style, write_priority, periphery, pin_layer, cells, + name, decoder, bit_folds, wrapper_verilog); + } + +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index 0797431e65..b40dd4616f 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -16,6 +16,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] ++ [-write_priority last|or] + [-cells {role master ...}] + [-name name] + [-decoder row|word] +@@ -28,6 +29,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-rb_ports count] + [-read_latency 0|1] + [-write_style clock_gate|mux] ++ [-write_priority last|or] + [-periphery placed|unplaced|verilog] + [-wrapper_verilog file] + [-pin_layer layer] +@@ -48,7 +50,7 @@ proc generate_ram_netlist { args } { + keys { -mask_size -word_size -num_words -column_mux_ratio -storage_cell -tristate_cell -inv_cell + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports -read_latency -write_style ++ -banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority + -periphery -pin_layer -cells -name -decoder -bit_folds -wrapper_verilog } flags {} + + set column_mux_ratio 1 +@@ -253,6 +255,16 @@ proc generate_ram_netlist { args } { + } + } + ++ # Where ports write the same word in a cycle: the last port's data ++ # (last), or the OR of every writing port's data (or). ++ set write_priority last ++ if { [info exists keys(-write_priority)] } { ++ set write_priority $keys(-write_priority) ++ if { $write_priority ni {last or} } { ++ utl::error RAM 87 "-write_priority is last or or, not $write_priority." ++ } ++ } ++ + # A read latency of 1: the read addresses registered. + set read_latency 0 + if { [info exists keys(-read_latency)] } { +@@ -275,7 +287,7 @@ proc generate_ram_netlist { args } { + ram::generate_ram_netlist_cmd $mask_size $word_size $num_words $rw_ports $r_ports $w_ports \ + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ +- $rb_ports $read_latency $write_style $periphery $pin_layer $cells $name \ ++ $rb_ports $read_latency $write_style $write_priority $periphery $pin_layer $cells $name \ + $decoder $bit_folds $wrapper_verilog + } + +@@ -311,7 +323,7 @@ proc generate_ram { args } { + -ground_net_name -routing_layer -ver_layer + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value +- -banks -bank_columns -bank_order -rb_ports -read_latency -write_style ++ -banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority + -cells -name -decoder -bit_folds } flags {} + + sta::check_argc_eq0 "generate_ram" $args +@@ -361,7 +373,7 @@ proc generate_ram { args } { + lappend ram_netlist_args -reset_value $keys(-reset_value) + } + +- foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style ++ foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority + -cells -name -decoder -bit_folds} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 77f753c358..602b9c13f3 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -15,6 +15,7 @@ COMPULSORY_TESTS = [ + PASSFAIL_TESTS = [ + "make_8x8_2r1w_unplaced_asap7", + "make_8x8_2r1w_mux_asap7", ++ "make_8x8_2r2w_or_asap7", + "make_8x8_rb_latency_asap7", + "make_8x8_rb_asap7", + "make_8x8_2r1w_banks_asap7", +@@ -90,6 +91,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_mux_asap7_behavioral.vok", + ], ++ "make_8x8_2r2w_or_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r2w_or_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_unplaced_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r2w_or_asap7.defok b/src/ram/test/make_8x8_2r2w_or_asap7.defok +new file mode 100644 +index 0000000000..80e7d91b14 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r2w_or_asap7.defok +@@ -0,0 +1,1222 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 2781 243 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 515 BY 1 STEP 5 0 ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 515 BY 1 STEP 5 0 ; ++COMPONENTS 524 ; ++ - buffer0.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 216 ) N ; ++ - buffer0.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 286 216 ) N ; ++ - buffer0.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 572 216 ) N ; ++ - buffer0.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 858 216 ) N ; ++ - buffer0.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 1144 216 ) N ; ++ - buffer0.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1431 216 ) N ; ++ - buffer0.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1717 216 ) N ; ++ - buffer0.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 2003 216 ) N ; ++ - buffer1.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 21 216 ) N ; ++ - buffer1.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 307 216 ) N ; ++ - buffer1.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 594 216 ) N ; ++ - buffer1.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 880 216 ) N ; ++ - buffer1.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 1166 216 ) N ; ++ - buffer1.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 1452 216 ) N ; ++ - buffer1.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1738 216 ) N ; ++ - buffer1.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 2025 216 ) N ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 2424 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 2424 27 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 2424 54 ) N ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 2424 81 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 2424 108 ) N ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 2424 135 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 2424 162 ) N ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 2424 189 ) FS ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2457 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2457 27 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2457 54 ) N ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2457 81 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2457 108 ) N ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2457 135 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2457 162 ) N ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2457 189 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 2748 108 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 2748 54 ) N ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 2748 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 2511 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 2511 27 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 2511 54 ) N ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 2511 81 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 2511 108 ) N ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 2511 135 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 2511 162 ) N ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 2511 189 ) FS ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2543 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2543 27 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2543 54 ) N ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2543 81 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2543 108 ) N ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2543 135 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2543 162 ) N ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2543 189 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 2748 135 ) FS ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 2748 81 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 2748 27 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 2597 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 2597 27 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 2597 54 ) N ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 2597 81 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 2597 108 ) N ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 2597 135 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 2597 162 ) N ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 2597 189 ) FS ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2629 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2629 27 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2629 54 ) N ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2629 81 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2629 108 ) N ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2629 135 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2629 162 ) N ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2629 189 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 2764 108 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 2764 54 ) N ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 2764 0 ) N ; ++ - decoder_p3.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 2683 0 ) N ; ++ - decoder_p3.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 2683 27 ) FS ; ++ - decoder_p3.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 2683 54 ) N ; ++ - decoder_p3.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 2683 81 ) FS ; ++ - decoder_p3.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 2683 108 ) N ; ++ - decoder_p3.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 2683 135 ) FS ; ++ - decoder_p3.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 2683 162 ) N ; ++ - decoder_p3.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 2683 189 ) FS ; ++ - decoder_p3.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 2716 0 ) N ; ++ - decoder_p3.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 2716 27 ) FS ; ++ - decoder_p3.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 2716 54 ) N ; ++ - decoder_p3.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 2716 81 ) FS ; ++ - decoder_p3.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 2716 108 ) N ; ++ - decoder_p3.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 2716 135 ) FS ; ++ - decoder_p3.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 2716 162 ) N ; ++ - decoder_p3.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 2716 189 ) FS ; ++ - decoder_p3.inv_p3_a0 INVx1_ASAP7_75t_R + PLACED ( 2764 135 ) FS ; ++ - decoder_p3.inv_p3_a1 INVx1_ASAP7_75t_R + PLACED ( 2764 81 ) FS ; ++ - decoder_p3.inv_p3_a2 INVx1_ASAP7_75t_R + PLACED ( 2764 27 ) FS ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 172 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 459 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 459 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 459 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 459 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 459 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 459 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 459 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 745 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 745 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 745 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 745 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 745 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 745 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 745 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1031 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1031 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1031 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1031 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1031 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1031 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1031 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1317 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1603 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1603 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1603 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1603 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1603 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1603 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1603 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1890 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1890 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1890 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1890 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1890 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1890 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1890 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 2176 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 2176 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 2176 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 2176 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2176 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2176 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2176 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 205 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 205 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 205 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 205 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 194 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 194 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 194 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 491 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 491 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 491 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 491 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 480 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 480 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 480 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 777 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 777 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 777 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 777 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 766 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 766 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 766 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1063 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1063 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1063 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1063 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1053 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1053 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1053 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1339 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1636 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1636 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1636 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1636 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1625 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1625 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1625 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1922 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1922 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1922 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1922 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1911 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1911 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1911 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 2208 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 2208 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 2208 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 2208 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 2197 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2197 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 2197 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 2575 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 2575 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 2575 54 ) N ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 2575 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 2575 108 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 2575 135 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 2575 162 ) N ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 2575 189 ) FS ; ++ - sel_buf_r_p3.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 2662 0 ) N ; ++ - sel_buf_r_p3.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 2662 27 ) FS ; ++ - sel_buf_r_p3.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 2662 54 ) N ; ++ - sel_buf_r_p3.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 2662 81 ) FS ; ++ - sel_buf_r_p3.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 2662 108 ) N ; ++ - sel_buf_r_p3.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 2662 135 ) FS ; ++ - sel_buf_r_p3.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 2662 162 ) N ; ++ - sel_buf_r_p3.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 2662 189 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 2403 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 2403 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 2403 54 ) N ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 2403 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 2403 108 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 2403 135 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 2403 162 ) N ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 2403 189 ) FS ; ++ - sel_buf_w_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 2489 0 ) N ; ++ - sel_buf_w_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 2489 27 ) FS ; ++ - sel_buf_w_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 2489 54 ) N ; ++ - sel_buf_w_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 2489 81 ) FS ; ++ - sel_buf_w_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 2489 108 ) N ; ++ - sel_buf_w_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 2489 135 ) FS ; ++ - sel_buf_w_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 2489 162 ) N ; ++ - sel_buf_w_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 2489 189 ) FS ; ++ - storage_0_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 0 ) N ; ++ - storage_0_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - storage_0_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 237 0 ) N ; ++ - storage_0_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 0 ) N ; ++ - storage_0_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 0 ) N ; ++ - storage_0_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 0 ) N ; ++ - storage_0_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 523 0 ) N ; ++ - storage_0_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 0 ) N ; ++ - storage_0_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 0 ) N ; ++ - storage_0_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 0 ) N ; ++ - storage_0_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 810 0 ) N ; ++ - storage_0_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 0 ) N ; ++ - storage_0_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 0 ) N ; ++ - storage_0_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 0 ) N ; ++ - storage_0_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1096 0 ) N ; ++ - storage_0_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 0 ) N ; ++ - storage_0_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 0 ) N ; ++ - storage_0_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 0 ) N ; ++ - storage_0_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1382 0 ) N ; ++ - storage_0_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 0 ) N ; ++ - storage_0_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 0 ) N ; ++ - storage_0_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 0 ) N ; ++ - storage_0_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1668 0 ) N ; ++ - storage_0_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 0 ) N ; ++ - storage_0_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 0 ) N ; ++ - storage_0_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 0 ) N ; ++ - storage_0_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1954 0 ) N ; ++ - storage_0_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 0 ) N ; ++ - storage_0_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 0 ) N ; ++ - storage_0_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 0 ) N ; ++ - storage_0_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2241 0 ) N ; ++ - storage_0_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 0 ) N ; ++ - storage_0_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 0 ) N ; ++ - storage_0_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 0 ) N ; ++ - storage_0_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 0 ) N ; ++ - storage_0_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 0 ) N ; ++ - storage_1_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 27 ) FS ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 216 27 ) FS ; ++ - storage_1_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 27 ) FS ; ++ - storage_1_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 27 ) FS ; ++ - storage_1_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 502 27 ) FS ; ++ - storage_1_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 27 ) FS ; ++ - storage_1_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 27 ) FS ; ++ - storage_1_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 788 27 ) FS ; ++ - storage_1_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 27 ) FS ; ++ - storage_1_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 27 ) FS ; ++ - storage_1_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1074 27 ) FS ; ++ - storage_1_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 27 ) FS ; ++ - storage_1_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - storage_1_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1360 27 ) FS ; ++ - storage_1_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 27 ) FS ; ++ - storage_1_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 27 ) FS ; ++ - storage_1_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1647 27 ) FS ; ++ - storage_1_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 27 ) FS ; ++ - storage_1_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 27 ) FS ; ++ - storage_1_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1933 27 ) FS ; ++ - storage_1_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 27 ) FS ; ++ - storage_1_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 27 ) FS ; ++ - storage_1_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2219 27 ) FS ; ++ - storage_1_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 27 ) FS ; ++ - storage_1_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 27 ) FS ; ++ - storage_1_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 27 ) FS ; ++ - storage_1_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 27 ) FS ; ++ - storage_1_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 27 ) FS ; ++ - storage_2_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 54 ) N ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 237 54 ) N ; ++ - storage_2_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 54 ) N ; ++ - storage_2_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 54 ) N ; ++ - storage_2_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 523 54 ) N ; ++ - storage_2_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 54 ) N ; ++ - storage_2_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 54 ) N ; ++ - storage_2_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 810 54 ) N ; ++ - storage_2_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 54 ) N ; ++ - storage_2_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 54 ) N ; ++ - storage_2_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1096 54 ) N ; ++ - storage_2_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 54 ) N ; ++ - storage_2_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - storage_2_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 54 ) N ; ++ - storage_2_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 54 ) N ; ++ - storage_2_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1668 54 ) N ; ++ - storage_2_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 54 ) N ; ++ - storage_2_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 54 ) N ; ++ - storage_2_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1954 54 ) N ; ++ - storage_2_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 54 ) N ; ++ - storage_2_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 54 ) N ; ++ - storage_2_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2241 54 ) N ; ++ - storage_2_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 54 ) N ; ++ - storage_2_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 54 ) N ; ++ - storage_2_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 54 ) N ; ++ - storage_2_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 54 ) N ; ++ - storage_2_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 54 ) N ; ++ - storage_3_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 81 ) FS ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 216 81 ) FS ; ++ - storage_3_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 81 ) FS ; ++ - storage_3_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 81 ) FS ; ++ - storage_3_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 502 81 ) FS ; ++ - storage_3_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 81 ) FS ; ++ - storage_3_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 81 ) FS ; ++ - storage_3_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 788 81 ) FS ; ++ - storage_3_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 81 ) FS ; ++ - storage_3_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 81 ) FS ; ++ - storage_3_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1074 81 ) FS ; ++ - storage_3_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 81 ) FS ; ++ - storage_3_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - storage_3_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1360 81 ) FS ; ++ - storage_3_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 81 ) FS ; ++ - storage_3_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 81 ) FS ; ++ - storage_3_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1647 81 ) FS ; ++ - storage_3_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 81 ) FS ; ++ - storage_3_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 81 ) FS ; ++ - storage_3_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1933 81 ) FS ; ++ - storage_3_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 81 ) FS ; ++ - storage_3_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 81 ) FS ; ++ - storage_3_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2219 81 ) FS ; ++ - storage_3_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 81 ) FS ; ++ - storage_3_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 81 ) FS ; ++ - storage_3_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 81 ) FS ; ++ - storage_3_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 81 ) FS ; ++ - storage_3_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 81 ) FS ; ++ - storage_4_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 108 ) N ; ++ - storage_4_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 237 108 ) N ; ++ - storage_4_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 108 ) N ; ++ - storage_4_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 108 ) N ; ++ - storage_4_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 523 108 ) N ; ++ - storage_4_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 108 ) N ; ++ - storage_4_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 108 ) N ; ++ - storage_4_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 810 108 ) N ; ++ - storage_4_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 108 ) N ; ++ - storage_4_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 108 ) N ; ++ - storage_4_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1096 108 ) N ; ++ - storage_4_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 108 ) N ; ++ - storage_4_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 108 ) N ; ++ - storage_4_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1382 108 ) N ; ++ - storage_4_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 108 ) N ; ++ - storage_4_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 108 ) N ; ++ - storage_4_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1668 108 ) N ; ++ - storage_4_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 108 ) N ; ++ - storage_4_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 108 ) N ; ++ - storage_4_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1954 108 ) N ; ++ - storage_4_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 108 ) N ; ++ - storage_4_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 108 ) N ; ++ - storage_4_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2241 108 ) N ; ++ - storage_4_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 108 ) N ; ++ - storage_4_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 108 ) N ; ++ - storage_4_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 108 ) N ; ++ - storage_4_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 108 ) N ; ++ - storage_4_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 108 ) N ; ++ - storage_5_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 135 ) FS ; ++ - storage_5_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 216 135 ) FS ; ++ - storage_5_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 135 ) FS ; ++ - storage_5_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 135 ) FS ; ++ - storage_5_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 502 135 ) FS ; ++ - storage_5_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 135 ) FS ; ++ - storage_5_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 135 ) FS ; ++ - storage_5_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 788 135 ) FS ; ++ - storage_5_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 135 ) FS ; ++ - storage_5_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 135 ) FS ; ++ - storage_5_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1074 135 ) FS ; ++ - storage_5_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 135 ) FS ; ++ - storage_5_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 135 ) FS ; ++ - storage_5_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1360 135 ) FS ; ++ - storage_5_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 135 ) FS ; ++ - storage_5_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 135 ) FS ; ++ - storage_5_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1647 135 ) FS ; ++ - storage_5_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 135 ) FS ; ++ - storage_5_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 135 ) FS ; ++ - storage_5_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1933 135 ) FS ; ++ - storage_5_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 135 ) FS ; ++ - storage_5_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 135 ) FS ; ++ - storage_5_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2219 135 ) FS ; ++ - storage_5_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 135 ) FS ; ++ - storage_5_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 135 ) FS ; ++ - storage_5_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 135 ) FS ; ++ - storage_5_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 135 ) FS ; ++ - storage_5_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 135 ) FS ; ++ - storage_6_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 162 ) N ; ++ - storage_6_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 237 162 ) N ; ++ - storage_6_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 162 ) N ; ++ - storage_6_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 162 ) N ; ++ - storage_6_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 523 162 ) N ; ++ - storage_6_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 162 ) N ; ++ - storage_6_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 162 ) N ; ++ - storage_6_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 810 162 ) N ; ++ - storage_6_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 162 ) N ; ++ - storage_6_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 162 ) N ; ++ - storage_6_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1096 162 ) N ; ++ - storage_6_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 162 ) N ; ++ - storage_6_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 162 ) N ; ++ - storage_6_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1382 162 ) N ; ++ - storage_6_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 162 ) N ; ++ - storage_6_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 162 ) N ; ++ - storage_6_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1668 162 ) N ; ++ - storage_6_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 162 ) N ; ++ - storage_6_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 162 ) N ; ++ - storage_6_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1954 162 ) N ; ++ - storage_6_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 162 ) N ; ++ - storage_6_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 162 ) N ; ++ - storage_6_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2241 162 ) N ; ++ - storage_6_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 162 ) N ; ++ - storage_6_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 162 ) N ; ++ - storage_6_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 162 ) N ; ++ - storage_6_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 162 ) N ; ++ - storage_6_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 162 ) N ; ++ - storage_7_0_0.any_or0 OR2x2_ASAP7_75t_R + PLACED ( 2370 189 ) FS ; ++ - storage_7_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit0.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 172 189 ) FS ; ++ - storage_7_0_0.bit0.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 124 189 ) FS ; ++ - storage_7_0_0.bit0.qinv INVx1_ASAP7_75t_R + PLACED ( 108 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 286 189 ) FS ; ++ - storage_7_0_0.bit1.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 459 189 ) FS ; ++ - storage_7_0_0.bit1.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 410 189 ) FS ; ++ - storage_7_0_0.bit1.qinv INVx1_ASAP7_75t_R + PLACED ( 394 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 572 189 ) FS ; ++ - storage_7_0_0.bit2.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 745 189 ) FS ; ++ - storage_7_0_0.bit2.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 696 189 ) FS ; ++ - storage_7_0_0.bit2.qinv INVx1_ASAP7_75t_R + PLACED ( 680 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 858 189 ) FS ; ++ - storage_7_0_0.bit3.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1031 189 ) FS ; ++ - storage_7_0_0.bit3.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 982 189 ) FS ; ++ - storage_7_0_0.bit3.qinv INVx1_ASAP7_75t_R + PLACED ( 966 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1144 189 ) FS ; ++ - storage_7_0_0.bit4.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1317 189 ) FS ; ++ - storage_7_0_0.bit4.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1269 189 ) FS ; ++ - storage_7_0_0.bit4.qinv INVx1_ASAP7_75t_R + PLACED ( 1252 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1431 189 ) FS ; ++ - storage_7_0_0.bit5.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1603 189 ) FS ; ++ - storage_7_0_0.bit5.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1555 189 ) FS ; ++ - storage_7_0_0.bit5.qinv INVx1_ASAP7_75t_R + PLACED ( 1539 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1717 189 ) FS ; ++ - storage_7_0_0.bit6.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 1890 189 ) FS ; ++ - storage_7_0_0.bit6.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 1841 189 ) FS ; ++ - storage_7_0_0.bit6.qinv INVx1_ASAP7_75t_R + PLACED ( 1825 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2003 189 ) FS ; ++ - storage_7_0_0.bit7.dmux0 AO22x1_ASAP7_75t_R + PLACED ( 2176 189 ) FS ; ++ - storage_7_0_0.bit7.hold_mux AO22x1_ASAP7_75t_R + PLACED ( 2127 189 ) FS ; ++ - storage_7_0_0.bit7.qinv INVx1_ASAP7_75t_R + PLACED ( 2111 189 ) FS ; ++ - storage_7_0_0.gcand0 AND2x2_ASAP7_75t_R + PLACED ( 2305 189 ) FS ; ++ - storage_7_0_0.gcand1 AND2x2_ASAP7_75t_R + PLACED ( 2338 189 ) FS ; ++ - storage_7_0_0.hold_inv INVx1_ASAP7_75t_R + PLACED ( 2289 189 ) FS ; ++END COMPONENTS ++PINS 47 ; ++ - D0[0] + NET D0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[1] + NET D0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[2] + NET D0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[3] + NET D0[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[4] + NET D0[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[5] + NET D0[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[6] + NET D0[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D0[7] + NET D0[7] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[0] + NET D1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[1] + NET D1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[2] + NET D1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[3] + NET D1[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[4] + NET D1[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[5] + NET D1[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[6] + NET D1[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D1[7] + NET D1[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w0[0] + NET addr_w0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w0[1] + NET addr_w0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w0[2] + NET addr_w0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w1[0] + NET addr_w1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w1[1] + NET addr_w1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w1[2] + NET addr_w1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we0[0] + NET we0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - we1[0] + NET we1[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 555 ; ++ - D0[0] ( PIN D0[0] ) ( buffer0.in[0] A ) + USE SIGNAL ; ++ - D0[1] ( PIN D0[1] ) ( buffer0.in[1] A ) + USE SIGNAL ; ++ - D0[2] ( PIN D0[2] ) ( buffer0.in[2] A ) + USE SIGNAL ; ++ - D0[3] ( PIN D0[3] ) ( buffer0.in[3] A ) + USE SIGNAL ; ++ - D0[4] ( PIN D0[4] ) ( buffer0.in[4] A ) + USE SIGNAL ; ++ - D0[5] ( PIN D0[5] ) ( buffer0.in[5] A ) + USE SIGNAL ; ++ - D0[6] ( PIN D0[6] ) ( buffer0.in[6] A ) + USE SIGNAL ; ++ - D0[7] ( PIN D0[7] ) ( buffer0.in[7] A ) + USE SIGNAL ; ++ - D0_nets.b0 ( buffer0.in[0] Y ) ( storage_7_0_0.bit0.dmux0 A2 ) ( storage_6_0_0.bit0.dmux0 A2 ) ( storage_5_0_0.bit0.dmux0 A2 ) ( storage_4_0_0.bit0.dmux0 A2 ) ( storage_3_0_0.bit0.dmux0 A2 ) ( storage_2_0_0.bit0.dmux0 A2 ) ++ ( storage_1_0_0.bit0.dmux0 A2 ) ( storage_0_0_0.bit0.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b1 ( buffer0.in[1] Y ) ( storage_7_0_0.bit1.dmux0 A2 ) ( storage_6_0_0.bit1.dmux0 A2 ) ( storage_5_0_0.bit1.dmux0 A2 ) ( storage_4_0_0.bit1.dmux0 A2 ) ( storage_3_0_0.bit1.dmux0 A2 ) ( storage_2_0_0.bit1.dmux0 A2 ) ++ ( storage_1_0_0.bit1.dmux0 A2 ) ( storage_0_0_0.bit1.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b2 ( buffer0.in[2] Y ) ( storage_7_0_0.bit2.dmux0 A2 ) ( storage_6_0_0.bit2.dmux0 A2 ) ( storage_5_0_0.bit2.dmux0 A2 ) ( storage_4_0_0.bit2.dmux0 A2 ) ( storage_3_0_0.bit2.dmux0 A2 ) ( storage_2_0_0.bit2.dmux0 A2 ) ++ ( storage_1_0_0.bit2.dmux0 A2 ) ( storage_0_0_0.bit2.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b3 ( buffer0.in[3] Y ) ( storage_7_0_0.bit3.dmux0 A2 ) ( storage_6_0_0.bit3.dmux0 A2 ) ( storage_5_0_0.bit3.dmux0 A2 ) ( storage_4_0_0.bit3.dmux0 A2 ) ( storage_3_0_0.bit3.dmux0 A2 ) ( storage_2_0_0.bit3.dmux0 A2 ) ++ ( storage_1_0_0.bit3.dmux0 A2 ) ( storage_0_0_0.bit3.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b4 ( buffer0.in[4] Y ) ( storage_7_0_0.bit4.dmux0 A2 ) ( storage_6_0_0.bit4.dmux0 A2 ) ( storage_5_0_0.bit4.dmux0 A2 ) ( storage_4_0_0.bit4.dmux0 A2 ) ( storage_3_0_0.bit4.dmux0 A2 ) ( storage_2_0_0.bit4.dmux0 A2 ) ++ ( storage_1_0_0.bit4.dmux0 A2 ) ( storage_0_0_0.bit4.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b5 ( buffer0.in[5] Y ) ( storage_7_0_0.bit5.dmux0 A2 ) ( storage_6_0_0.bit5.dmux0 A2 ) ( storage_5_0_0.bit5.dmux0 A2 ) ( storage_4_0_0.bit5.dmux0 A2 ) ( storage_3_0_0.bit5.dmux0 A2 ) ( storage_2_0_0.bit5.dmux0 A2 ) ++ ( storage_1_0_0.bit5.dmux0 A2 ) ( storage_0_0_0.bit5.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b6 ( buffer0.in[6] Y ) ( storage_7_0_0.bit6.dmux0 A2 ) ( storage_6_0_0.bit6.dmux0 A2 ) ( storage_5_0_0.bit6.dmux0 A2 ) ( storage_4_0_0.bit6.dmux0 A2 ) ( storage_3_0_0.bit6.dmux0 A2 ) ( storage_2_0_0.bit6.dmux0 A2 ) ++ ( storage_1_0_0.bit6.dmux0 A2 ) ( storage_0_0_0.bit6.dmux0 A2 ) + USE SIGNAL ; ++ - D0_nets.b7 ( buffer0.in[7] Y ) ( storage_7_0_0.bit7.dmux0 A2 ) ( storage_6_0_0.bit7.dmux0 A2 ) ( storage_5_0_0.bit7.dmux0 A2 ) ( storage_4_0_0.bit7.dmux0 A2 ) ( storage_3_0_0.bit7.dmux0 A2 ) ( storage_2_0_0.bit7.dmux0 A2 ) ++ ( storage_1_0_0.bit7.dmux0 A2 ) ( storage_0_0_0.bit7.dmux0 A2 ) + USE SIGNAL ; ++ - D1[0] ( PIN D1[0] ) ( buffer1.in[0] A ) + USE SIGNAL ; ++ - D1[1] ( PIN D1[1] ) ( buffer1.in[1] A ) + USE SIGNAL ; ++ - D1[2] ( PIN D1[2] ) ( buffer1.in[2] A ) + USE SIGNAL ; ++ - D1[3] ( PIN D1[3] ) ( buffer1.in[3] A ) + USE SIGNAL ; ++ - D1[4] ( PIN D1[4] ) ( buffer1.in[4] A ) + USE SIGNAL ; ++ - D1[5] ( PIN D1[5] ) ( buffer1.in[5] A ) + USE SIGNAL ; ++ - D1[6] ( PIN D1[6] ) ( buffer1.in[6] A ) + USE SIGNAL ; ++ - D1[7] ( PIN D1[7] ) ( buffer1.in[7] A ) + USE SIGNAL ; ++ - D1_nets.b0 ( buffer1.in[0] Y ) ( storage_7_0_0.bit0.dmux0 B2 ) ( storage_6_0_0.bit0.dmux0 B2 ) ( storage_5_0_0.bit0.dmux0 B2 ) ( storage_4_0_0.bit0.dmux0 B2 ) ( storage_3_0_0.bit0.dmux0 B2 ) ( storage_2_0_0.bit0.dmux0 B2 ) ++ ( storage_1_0_0.bit0.dmux0 B2 ) ( storage_0_0_0.bit0.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b1 ( buffer1.in[1] Y ) ( storage_7_0_0.bit1.dmux0 B2 ) ( storage_6_0_0.bit1.dmux0 B2 ) ( storage_5_0_0.bit1.dmux0 B2 ) ( storage_4_0_0.bit1.dmux0 B2 ) ( storage_3_0_0.bit1.dmux0 B2 ) ( storage_2_0_0.bit1.dmux0 B2 ) ++ ( storage_1_0_0.bit1.dmux0 B2 ) ( storage_0_0_0.bit1.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b2 ( buffer1.in[2] Y ) ( storage_7_0_0.bit2.dmux0 B2 ) ( storage_6_0_0.bit2.dmux0 B2 ) ( storage_5_0_0.bit2.dmux0 B2 ) ( storage_4_0_0.bit2.dmux0 B2 ) ( storage_3_0_0.bit2.dmux0 B2 ) ( storage_2_0_0.bit2.dmux0 B2 ) ++ ( storage_1_0_0.bit2.dmux0 B2 ) ( storage_0_0_0.bit2.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b3 ( buffer1.in[3] Y ) ( storage_7_0_0.bit3.dmux0 B2 ) ( storage_6_0_0.bit3.dmux0 B2 ) ( storage_5_0_0.bit3.dmux0 B2 ) ( storage_4_0_0.bit3.dmux0 B2 ) ( storage_3_0_0.bit3.dmux0 B2 ) ( storage_2_0_0.bit3.dmux0 B2 ) ++ ( storage_1_0_0.bit3.dmux0 B2 ) ( storage_0_0_0.bit3.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b4 ( buffer1.in[4] Y ) ( storage_7_0_0.bit4.dmux0 B2 ) ( storage_6_0_0.bit4.dmux0 B2 ) ( storage_5_0_0.bit4.dmux0 B2 ) ( storage_4_0_0.bit4.dmux0 B2 ) ( storage_3_0_0.bit4.dmux0 B2 ) ( storage_2_0_0.bit4.dmux0 B2 ) ++ ( storage_1_0_0.bit4.dmux0 B2 ) ( storage_0_0_0.bit4.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b5 ( buffer1.in[5] Y ) ( storage_7_0_0.bit5.dmux0 B2 ) ( storage_6_0_0.bit5.dmux0 B2 ) ( storage_5_0_0.bit5.dmux0 B2 ) ( storage_4_0_0.bit5.dmux0 B2 ) ( storage_3_0_0.bit5.dmux0 B2 ) ( storage_2_0_0.bit5.dmux0 B2 ) ++ ( storage_1_0_0.bit5.dmux0 B2 ) ( storage_0_0_0.bit5.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b6 ( buffer1.in[6] Y ) ( storage_7_0_0.bit6.dmux0 B2 ) ( storage_6_0_0.bit6.dmux0 B2 ) ( storage_5_0_0.bit6.dmux0 B2 ) ( storage_4_0_0.bit6.dmux0 B2 ) ( storage_3_0_0.bit6.dmux0 B2 ) ( storage_2_0_0.bit6.dmux0 B2 ) ++ ( storage_1_0_0.bit6.dmux0 B2 ) ( storage_0_0_0.bit6.dmux0 B2 ) + USE SIGNAL ; ++ - D1_nets.b7 ( buffer1.in[7] Y ) ( storage_7_0_0.bit7.dmux0 B2 ) ( storage_6_0_0.bit7.dmux0 B2 ) ( storage_5_0_0.bit7.dmux0 B2 ) ( storage_4_0_0.bit7.dmux0 B2 ) ( storage_3_0_0.bit7.dmux0 B2 ) ( storage_2_0_0.bit7.dmux0 B2 ) ++ ( storage_1_0_0.bit7.dmux0 B2 ) ( storage_0_0_0.bit7.dmux0 B2 ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p3.inv_p3_a0 Y ) ( decoder_p3.and_layer0_word6 A ) ( decoder_p3.and_layer0_word4 A ) ( decoder_p3.and_layer0_word2 A ) ( decoder_p3.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p3.inv_p3_a1 Y ) ( decoder_p3.and_layer1_word5 A ) ( decoder_p3.and_layer1_word4 A ) ( decoder_p3.and_layer1_word1 A ) ( decoder_p3.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p3.inv_p3_a2 Y ) ( decoder_p3.and_layer1_word3 B ) ( decoder_p3.and_layer1_word2 B ) ( decoder_p3.and_layer1_word1 B ) ( decoder_p3.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p3.inv_p3_a0 A ) ( decoder_p3.and_layer0_word7 A ) ( decoder_p3.and_layer0_word5 A ) ( decoder_p3.and_layer0_word3 A ) ( decoder_p3.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p3.inv_p3_a1 A ) ( decoder_p3.and_layer1_word7 A ) ( decoder_p3.and_layer1_word6 A ) ( decoder_p3.and_layer1_word3 A ) ( decoder_p3.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p3.inv_p3_a2 A ) ( decoder_p3.and_layer1_word7 B ) ( decoder_p3.and_layer1_word6 B ) ( decoder_p3.and_layer1_word5 B ) ( decoder_p3.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w0.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w0.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w0.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w0[0] ( PIN addr_w0[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w0[1] ( PIN addr_w0[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w0[2] ( PIN addr_w0[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w1.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w1.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w1.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w1[0] ( PIN addr_w1[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w1[1] ( PIN addr_w1[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w1[2] ( PIN addr_w1[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) ( storage_0_0_0.bit7.bit CLK ) ( storage_0_0_0.bit6.bit CLK ) ( storage_0_0_0.bit5.bit CLK ) ( storage_0_0_0.bit4.bit CLK ) ( storage_0_0_0.bit3.bit CLK ) ( storage_0_0_0.bit2.bit CLK ) ++ ( storage_0_0_0.bit1.bit CLK ) ( storage_0_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_w_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_w_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_w_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_w_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_w_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_w_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_w_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_w_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word0 ( decoder_p3.and_layer1_word0 Y ) ( decoder_p3.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word1 ( decoder_p3.and_layer1_word1 Y ) ( decoder_p3.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word2 ( decoder_p3.and_layer1_word2 Y ) ( decoder_p3.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word3 ( decoder_p3.and_layer1_word3 Y ) ( decoder_p3.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word4 ( decoder_p3.and_layer1_word4 Y ) ( decoder_p3.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word5 ( decoder_p3.and_layer1_word5 Y ) ( decoder_p3.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word6 ( decoder_p3.and_layer1_word6 Y ) ( decoder_p3.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p3.layer_in0_word7 ( decoder_p3.and_layer1_word7 Y ) ( decoder_p3.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p3.word0 ( decoder_p3.and_layer0_word0 Y ) ( sel_buf_r_p3.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p3.word1 ( decoder_p3.and_layer0_word1 Y ) ( sel_buf_r_p3.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p3.word2 ( decoder_p3.and_layer0_word2 Y ) ( sel_buf_r_p3.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p3.word3 ( decoder_p3.and_layer0_word3 Y ) ( sel_buf_r_p3.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p3.word4 ( decoder_p3.and_layer0_word4 Y ) ( sel_buf_r_p3.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p3.word5 ( decoder_p3.and_layer0_word5 Y ) ( sel_buf_r_p3.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p3.word6 ( decoder_p3.and_layer0_word6 Y ) ( sel_buf_r_p3.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p3.word7 ( decoder_p3.and_layer0_word7 Y ) ( sel_buf_r_p3.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A1 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A1 ) ++ ( read_w0_p0_b1.aoi_r0 A1 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r0 ( sel_buf_r_p3.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A1 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A1 ) ++ ( read_w0_p1_b1.aoi_r0 A1 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r1 ( sel_buf_r_p3.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r2 ( sel_buf_r_p3.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r3 ( sel_buf_r_p3.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r4 ( sel_buf_r_p3.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r5 ( sel_buf_r_p3.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r6 ( sel_buf_r_p3.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p3.select_r7 ( sel_buf_r_p3.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.d ( storage_0_0_0.bit0.dmux0 Y ) ( storage_0_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.dhold ( storage_0_0_0.bit0.hold_mux Y ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.q ( storage_0_0_0.bit0.hold_mux B2 ) ( storage_0_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.storage ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A2 ) ( storage_0_0_0.bit0.qinv A ) ( storage_0_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.d ( storage_0_0_0.bit1.dmux0 Y ) ( storage_0_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.dhold ( storage_0_0_0.bit1.hold_mux Y ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.q ( storage_0_0_0.bit1.hold_mux B2 ) ( storage_0_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.storage ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( storage_0_0_0.bit1.qinv A ) ( storage_0_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.d ( storage_0_0_0.bit2.dmux0 Y ) ( storage_0_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.dhold ( storage_0_0_0.bit2.hold_mux Y ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.q ( storage_0_0_0.bit2.hold_mux B2 ) ( storage_0_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.storage ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( storage_0_0_0.bit2.qinv A ) ( storage_0_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.d ( storage_0_0_0.bit3.dmux0 Y ) ( storage_0_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.dhold ( storage_0_0_0.bit3.hold_mux Y ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.q ( storage_0_0_0.bit3.hold_mux B2 ) ( storage_0_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.storage ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( storage_0_0_0.bit3.qinv A ) ( storage_0_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.d ( storage_0_0_0.bit4.dmux0 Y ) ( storage_0_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.dhold ( storage_0_0_0.bit4.hold_mux Y ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.q ( storage_0_0_0.bit4.hold_mux B2 ) ( storage_0_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.storage ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A2 ) ( storage_0_0_0.bit4.qinv A ) ( storage_0_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.d ( storage_0_0_0.bit5.dmux0 Y ) ( storage_0_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.dhold ( storage_0_0_0.bit5.hold_mux Y ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.q ( storage_0_0_0.bit5.hold_mux B2 ) ( storage_0_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.storage ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( storage_0_0_0.bit5.qinv A ) ( storage_0_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.d ( storage_0_0_0.bit6.dmux0 Y ) ( storage_0_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.dhold ( storage_0_0_0.bit6.hold_mux Y ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.q ( storage_0_0_0.bit6.hold_mux B2 ) ( storage_0_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.storage ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( storage_0_0_0.bit6.qinv A ) ( storage_0_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.d ( storage_0_0_0.bit7.dmux0 Y ) ( storage_0_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.dhold ( storage_0_0_0.bit7.hold_mux Y ) ( storage_0_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.q ( storage_0_0_0.bit7.hold_mux B2 ) ( storage_0_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.storage ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A2 ) ( storage_0_0_0.bit7.qinv A ) ( storage_0_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.hold ( storage_0_0_0.bit7.hold_mux B1 ) ( storage_0_0_0.bit6.hold_mux B1 ) ( storage_0_0_0.bit5.hold_mux B1 ) ( storage_0_0_0.bit4.hold_mux B1 ) ( storage_0_0_0.bit3.hold_mux B1 ) ( storage_0_0_0.bit2.hold_mux B1 ) ( storage_0_0_0.bit1.hold_mux B1 ) ++ ( storage_0_0_0.bit0.hold_mux B1 ) ( storage_0_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_0_0_0.we ( storage_0_0_0.bit7.hold_mux A1 ) ( storage_0_0_0.bit6.hold_mux A1 ) ( storage_0_0_0.bit5.hold_mux A1 ) ( storage_0_0_0.bit4.hold_mux A1 ) ( storage_0_0_0.bit3.hold_mux A1 ) ( storage_0_0_0.bit2.hold_mux A1 ) ( storage_0_0_0.bit1.hold_mux A1 ) ++ ( storage_0_0_0.bit0.hold_mux A1 ) ( storage_0_0_0.any_or0 Y ) ( storage_0_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_0_0_0.we0 ( storage_0_0_0.bit7.dmux0 A1 ) ( storage_0_0_0.bit6.dmux0 A1 ) ( storage_0_0_0.bit5.dmux0 A1 ) ( storage_0_0_0.bit4.dmux0 A1 ) ( storage_0_0_0.bit3.dmux0 A1 ) ( storage_0_0_0.bit2.dmux0 A1 ) ( storage_0_0_0.bit1.dmux0 A1 ) ++ ( storage_0_0_0.bit0.dmux0 A1 ) ( storage_0_0_0.any_or0 B ) ( storage_0_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_0_0_0.we1 ( storage_0_0_0.bit7.dmux0 B1 ) ( storage_0_0_0.bit6.dmux0 B1 ) ( storage_0_0_0.bit5.dmux0 B1 ) ( storage_0_0_0.bit4.dmux0 B1 ) ( storage_0_0_0.bit3.dmux0 B1 ) ( storage_0_0_0.bit2.dmux0 B1 ) ( storage_0_0_0.bit1.dmux0 B1 ) ++ ( storage_0_0_0.bit0.dmux0 B1 ) ( storage_0_0_0.any_or0 A ) ( storage_0_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.d ( storage_1_0_0.bit0.dmux0 Y ) ( storage_1_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.dhold ( storage_1_0_0.bit0.hold_mux Y ) ( storage_1_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.q ( storage_1_0_0.bit0.hold_mux B2 ) ( storage_1_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.qinv A ) ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.d ( storage_1_0_0.bit1.dmux0 Y ) ( storage_1_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.dhold ( storage_1_0_0.bit1.hold_mux Y ) ( storage_1_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.q ( storage_1_0_0.bit1.hold_mux B2 ) ( storage_1_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.qinv A ) ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.d ( storage_1_0_0.bit2.dmux0 Y ) ( storage_1_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.dhold ( storage_1_0_0.bit2.hold_mux Y ) ( storage_1_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.q ( storage_1_0_0.bit2.hold_mux B2 ) ( storage_1_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.qinv A ) ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.d ( storage_1_0_0.bit3.dmux0 Y ) ( storage_1_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.dhold ( storage_1_0_0.bit3.hold_mux Y ) ( storage_1_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.q ( storage_1_0_0.bit3.hold_mux B2 ) ( storage_1_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.qinv A ) ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.d ( storage_1_0_0.bit4.dmux0 Y ) ( storage_1_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.dhold ( storage_1_0_0.bit4.hold_mux Y ) ( storage_1_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.q ( storage_1_0_0.bit4.hold_mux B2 ) ( storage_1_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.qinv A ) ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.d ( storage_1_0_0.bit5.dmux0 Y ) ( storage_1_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.dhold ( storage_1_0_0.bit5.hold_mux Y ) ( storage_1_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.q ( storage_1_0_0.bit5.hold_mux B2 ) ( storage_1_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.qinv A ) ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.d ( storage_1_0_0.bit6.dmux0 Y ) ( storage_1_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.dhold ( storage_1_0_0.bit6.hold_mux Y ) ( storage_1_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.q ( storage_1_0_0.bit6.hold_mux B2 ) ( storage_1_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.qinv A ) ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.d ( storage_1_0_0.bit7.dmux0 Y ) ( storage_1_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.dhold ( storage_1_0_0.bit7.hold_mux Y ) ( storage_1_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.q ( storage_1_0_0.bit7.hold_mux B2 ) ( storage_1_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.qinv A ) ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.hold ( storage_1_0_0.bit7.hold_mux B1 ) ( storage_1_0_0.bit6.hold_mux B1 ) ( storage_1_0_0.bit5.hold_mux B1 ) ( storage_1_0_0.bit4.hold_mux B1 ) ( storage_1_0_0.bit3.hold_mux B1 ) ( storage_1_0_0.bit2.hold_mux B1 ) ( storage_1_0_0.bit1.hold_mux B1 ) ++ ( storage_1_0_0.bit0.hold_mux B1 ) ( storage_1_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.bit7.hold_mux A1 ) ( storage_1_0_0.bit6.hold_mux A1 ) ( storage_1_0_0.bit5.hold_mux A1 ) ( storage_1_0_0.bit4.hold_mux A1 ) ( storage_1_0_0.bit3.hold_mux A1 ) ( storage_1_0_0.bit2.hold_mux A1 ) ( storage_1_0_0.bit1.hold_mux A1 ) ++ ( storage_1_0_0.bit0.hold_mux A1 ) ( storage_1_0_0.any_or0 Y ) ( storage_1_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_1_0_0.we0 ( storage_1_0_0.bit7.dmux0 A1 ) ( storage_1_0_0.bit6.dmux0 A1 ) ( storage_1_0_0.bit5.dmux0 A1 ) ( storage_1_0_0.bit4.dmux0 A1 ) ( storage_1_0_0.bit3.dmux0 A1 ) ( storage_1_0_0.bit2.dmux0 A1 ) ( storage_1_0_0.bit1.dmux0 A1 ) ++ ( storage_1_0_0.bit0.dmux0 A1 ) ( storage_1_0_0.any_or0 B ) ( storage_1_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_1_0_0.we1 ( storage_1_0_0.bit7.dmux0 B1 ) ( storage_1_0_0.bit6.dmux0 B1 ) ( storage_1_0_0.bit5.dmux0 B1 ) ( storage_1_0_0.bit4.dmux0 B1 ) ( storage_1_0_0.bit3.dmux0 B1 ) ( storage_1_0_0.bit2.dmux0 B1 ) ( storage_1_0_0.bit1.dmux0 B1 ) ++ ( storage_1_0_0.bit0.dmux0 B1 ) ( storage_1_0_0.any_or0 A ) ( storage_1_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.d ( storage_2_0_0.bit0.dmux0 Y ) ( storage_2_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.dhold ( storage_2_0_0.bit0.hold_mux Y ) ( storage_2_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.q ( storage_2_0_0.bit0.hold_mux B2 ) ( storage_2_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.qinv A ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.d ( storage_2_0_0.bit1.dmux0 Y ) ( storage_2_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.dhold ( storage_2_0_0.bit1.hold_mux Y ) ( storage_2_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.q ( storage_2_0_0.bit1.hold_mux B2 ) ( storage_2_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.qinv A ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.d ( storage_2_0_0.bit2.dmux0 Y ) ( storage_2_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.dhold ( storage_2_0_0.bit2.hold_mux Y ) ( storage_2_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.q ( storage_2_0_0.bit2.hold_mux B2 ) ( storage_2_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.qinv A ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.d ( storage_2_0_0.bit3.dmux0 Y ) ( storage_2_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.dhold ( storage_2_0_0.bit3.hold_mux Y ) ( storage_2_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.q ( storage_2_0_0.bit3.hold_mux B2 ) ( storage_2_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.qinv A ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.d ( storage_2_0_0.bit4.dmux0 Y ) ( storage_2_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.dhold ( storage_2_0_0.bit4.hold_mux Y ) ( storage_2_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.q ( storage_2_0_0.bit4.hold_mux B2 ) ( storage_2_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.qinv A ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.d ( storage_2_0_0.bit5.dmux0 Y ) ( storage_2_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.dhold ( storage_2_0_0.bit5.hold_mux Y ) ( storage_2_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.q ( storage_2_0_0.bit5.hold_mux B2 ) ( storage_2_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.qinv A ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.d ( storage_2_0_0.bit6.dmux0 Y ) ( storage_2_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.dhold ( storage_2_0_0.bit6.hold_mux Y ) ( storage_2_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.q ( storage_2_0_0.bit6.hold_mux B2 ) ( storage_2_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.qinv A ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.d ( storage_2_0_0.bit7.dmux0 Y ) ( storage_2_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.dhold ( storage_2_0_0.bit7.hold_mux Y ) ( storage_2_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.q ( storage_2_0_0.bit7.hold_mux B2 ) ( storage_2_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.qinv A ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.hold ( storage_2_0_0.bit7.hold_mux B1 ) ( storage_2_0_0.bit6.hold_mux B1 ) ( storage_2_0_0.bit5.hold_mux B1 ) ( storage_2_0_0.bit4.hold_mux B1 ) ( storage_2_0_0.bit3.hold_mux B1 ) ( storage_2_0_0.bit2.hold_mux B1 ) ( storage_2_0_0.bit1.hold_mux B1 ) ++ ( storage_2_0_0.bit0.hold_mux B1 ) ( storage_2_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.bit7.hold_mux A1 ) ( storage_2_0_0.bit6.hold_mux A1 ) ( storage_2_0_0.bit5.hold_mux A1 ) ( storage_2_0_0.bit4.hold_mux A1 ) ( storage_2_0_0.bit3.hold_mux A1 ) ( storage_2_0_0.bit2.hold_mux A1 ) ( storage_2_0_0.bit1.hold_mux A1 ) ++ ( storage_2_0_0.bit0.hold_mux A1 ) ( storage_2_0_0.any_or0 Y ) ( storage_2_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_2_0_0.we0 ( storage_2_0_0.bit7.dmux0 A1 ) ( storage_2_0_0.bit6.dmux0 A1 ) ( storage_2_0_0.bit5.dmux0 A1 ) ( storage_2_0_0.bit4.dmux0 A1 ) ( storage_2_0_0.bit3.dmux0 A1 ) ( storage_2_0_0.bit2.dmux0 A1 ) ( storage_2_0_0.bit1.dmux0 A1 ) ++ ( storage_2_0_0.bit0.dmux0 A1 ) ( storage_2_0_0.any_or0 B ) ( storage_2_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_2_0_0.we1 ( storage_2_0_0.bit7.dmux0 B1 ) ( storage_2_0_0.bit6.dmux0 B1 ) ( storage_2_0_0.bit5.dmux0 B1 ) ( storage_2_0_0.bit4.dmux0 B1 ) ( storage_2_0_0.bit3.dmux0 B1 ) ( storage_2_0_0.bit2.dmux0 B1 ) ( storage_2_0_0.bit1.dmux0 B1 ) ++ ( storage_2_0_0.bit0.dmux0 B1 ) ( storage_2_0_0.any_or0 A ) ( storage_2_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.d ( storage_3_0_0.bit0.dmux0 Y ) ( storage_3_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.dhold ( storage_3_0_0.bit0.hold_mux Y ) ( storage_3_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.q ( storage_3_0_0.bit0.hold_mux B2 ) ( storage_3_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.qinv A ) ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.d ( storage_3_0_0.bit1.dmux0 Y ) ( storage_3_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.dhold ( storage_3_0_0.bit1.hold_mux Y ) ( storage_3_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.q ( storage_3_0_0.bit1.hold_mux B2 ) ( storage_3_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.qinv A ) ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.d ( storage_3_0_0.bit2.dmux0 Y ) ( storage_3_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.dhold ( storage_3_0_0.bit2.hold_mux Y ) ( storage_3_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.q ( storage_3_0_0.bit2.hold_mux B2 ) ( storage_3_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.qinv A ) ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.d ( storage_3_0_0.bit3.dmux0 Y ) ( storage_3_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.dhold ( storage_3_0_0.bit3.hold_mux Y ) ( storage_3_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.q ( storage_3_0_0.bit3.hold_mux B2 ) ( storage_3_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.qinv A ) ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.d ( storage_3_0_0.bit4.dmux0 Y ) ( storage_3_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.dhold ( storage_3_0_0.bit4.hold_mux Y ) ( storage_3_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.q ( storage_3_0_0.bit4.hold_mux B2 ) ( storage_3_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.qinv A ) ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.d ( storage_3_0_0.bit5.dmux0 Y ) ( storage_3_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.dhold ( storage_3_0_0.bit5.hold_mux Y ) ( storage_3_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.q ( storage_3_0_0.bit5.hold_mux B2 ) ( storage_3_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.qinv A ) ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.d ( storage_3_0_0.bit6.dmux0 Y ) ( storage_3_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.dhold ( storage_3_0_0.bit6.hold_mux Y ) ( storage_3_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.q ( storage_3_0_0.bit6.hold_mux B2 ) ( storage_3_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.qinv A ) ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.d ( storage_3_0_0.bit7.dmux0 Y ) ( storage_3_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.dhold ( storage_3_0_0.bit7.hold_mux Y ) ( storage_3_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.q ( storage_3_0_0.bit7.hold_mux B2 ) ( storage_3_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.qinv A ) ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.hold ( storage_3_0_0.bit7.hold_mux B1 ) ( storage_3_0_0.bit6.hold_mux B1 ) ( storage_3_0_0.bit5.hold_mux B1 ) ( storage_3_0_0.bit4.hold_mux B1 ) ( storage_3_0_0.bit3.hold_mux B1 ) ( storage_3_0_0.bit2.hold_mux B1 ) ( storage_3_0_0.bit1.hold_mux B1 ) ++ ( storage_3_0_0.bit0.hold_mux B1 ) ( storage_3_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.bit7.hold_mux A1 ) ( storage_3_0_0.bit6.hold_mux A1 ) ( storage_3_0_0.bit5.hold_mux A1 ) ( storage_3_0_0.bit4.hold_mux A1 ) ( storage_3_0_0.bit3.hold_mux A1 ) ( storage_3_0_0.bit2.hold_mux A1 ) ( storage_3_0_0.bit1.hold_mux A1 ) ++ ( storage_3_0_0.bit0.hold_mux A1 ) ( storage_3_0_0.any_or0 Y ) ( storage_3_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_3_0_0.we0 ( storage_3_0_0.bit7.dmux0 A1 ) ( storage_3_0_0.bit6.dmux0 A1 ) ( storage_3_0_0.bit5.dmux0 A1 ) ( storage_3_0_0.bit4.dmux0 A1 ) ( storage_3_0_0.bit3.dmux0 A1 ) ( storage_3_0_0.bit2.dmux0 A1 ) ( storage_3_0_0.bit1.dmux0 A1 ) ++ ( storage_3_0_0.bit0.dmux0 A1 ) ( storage_3_0_0.any_or0 B ) ( storage_3_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_3_0_0.we1 ( storage_3_0_0.bit7.dmux0 B1 ) ( storage_3_0_0.bit6.dmux0 B1 ) ( storage_3_0_0.bit5.dmux0 B1 ) ( storage_3_0_0.bit4.dmux0 B1 ) ( storage_3_0_0.bit3.dmux0 B1 ) ( storage_3_0_0.bit2.dmux0 B1 ) ( storage_3_0_0.bit1.dmux0 B1 ) ++ ( storage_3_0_0.bit0.dmux0 B1 ) ( storage_3_0_0.any_or0 A ) ( storage_3_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.d ( storage_4_0_0.bit0.dmux0 Y ) ( storage_4_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.dhold ( storage_4_0_0.bit0.hold_mux Y ) ( storage_4_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.q ( storage_4_0_0.bit0.hold_mux B2 ) ( storage_4_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.qinv A ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.d ( storage_4_0_0.bit1.dmux0 Y ) ( storage_4_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.dhold ( storage_4_0_0.bit1.hold_mux Y ) ( storage_4_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.q ( storage_4_0_0.bit1.hold_mux B2 ) ( storage_4_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.qinv A ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.d ( storage_4_0_0.bit2.dmux0 Y ) ( storage_4_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.dhold ( storage_4_0_0.bit2.hold_mux Y ) ( storage_4_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.q ( storage_4_0_0.bit2.hold_mux B2 ) ( storage_4_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.qinv A ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.d ( storage_4_0_0.bit3.dmux0 Y ) ( storage_4_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.dhold ( storage_4_0_0.bit3.hold_mux Y ) ( storage_4_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.q ( storage_4_0_0.bit3.hold_mux B2 ) ( storage_4_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.qinv A ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.d ( storage_4_0_0.bit4.dmux0 Y ) ( storage_4_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.dhold ( storage_4_0_0.bit4.hold_mux Y ) ( storage_4_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.q ( storage_4_0_0.bit4.hold_mux B2 ) ( storage_4_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.qinv A ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.d ( storage_4_0_0.bit5.dmux0 Y ) ( storage_4_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.dhold ( storage_4_0_0.bit5.hold_mux Y ) ( storage_4_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.q ( storage_4_0_0.bit5.hold_mux B2 ) ( storage_4_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.qinv A ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.d ( storage_4_0_0.bit6.dmux0 Y ) ( storage_4_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.dhold ( storage_4_0_0.bit6.hold_mux Y ) ( storage_4_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.q ( storage_4_0_0.bit6.hold_mux B2 ) ( storage_4_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.qinv A ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.d ( storage_4_0_0.bit7.dmux0 Y ) ( storage_4_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.dhold ( storage_4_0_0.bit7.hold_mux Y ) ( storage_4_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.q ( storage_4_0_0.bit7.hold_mux B2 ) ( storage_4_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.qinv A ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.hold ( storage_4_0_0.bit7.hold_mux B1 ) ( storage_4_0_0.bit6.hold_mux B1 ) ( storage_4_0_0.bit5.hold_mux B1 ) ( storage_4_0_0.bit4.hold_mux B1 ) ( storage_4_0_0.bit3.hold_mux B1 ) ( storage_4_0_0.bit2.hold_mux B1 ) ( storage_4_0_0.bit1.hold_mux B1 ) ++ ( storage_4_0_0.bit0.hold_mux B1 ) ( storage_4_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.bit7.hold_mux A1 ) ( storage_4_0_0.bit6.hold_mux A1 ) ( storage_4_0_0.bit5.hold_mux A1 ) ( storage_4_0_0.bit4.hold_mux A1 ) ( storage_4_0_0.bit3.hold_mux A1 ) ( storage_4_0_0.bit2.hold_mux A1 ) ( storage_4_0_0.bit1.hold_mux A1 ) ++ ( storage_4_0_0.bit0.hold_mux A1 ) ( storage_4_0_0.any_or0 Y ) ( storage_4_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_4_0_0.we0 ( storage_4_0_0.bit7.dmux0 A1 ) ( storage_4_0_0.bit6.dmux0 A1 ) ( storage_4_0_0.bit5.dmux0 A1 ) ( storage_4_0_0.bit4.dmux0 A1 ) ( storage_4_0_0.bit3.dmux0 A1 ) ( storage_4_0_0.bit2.dmux0 A1 ) ( storage_4_0_0.bit1.dmux0 A1 ) ++ ( storage_4_0_0.bit0.dmux0 A1 ) ( storage_4_0_0.any_or0 B ) ( storage_4_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_4_0_0.we1 ( storage_4_0_0.bit7.dmux0 B1 ) ( storage_4_0_0.bit6.dmux0 B1 ) ( storage_4_0_0.bit5.dmux0 B1 ) ( storage_4_0_0.bit4.dmux0 B1 ) ( storage_4_0_0.bit3.dmux0 B1 ) ( storage_4_0_0.bit2.dmux0 B1 ) ( storage_4_0_0.bit1.dmux0 B1 ) ++ ( storage_4_0_0.bit0.dmux0 B1 ) ( storage_4_0_0.any_or0 A ) ( storage_4_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.d ( storage_5_0_0.bit0.dmux0 Y ) ( storage_5_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.dhold ( storage_5_0_0.bit0.hold_mux Y ) ( storage_5_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.q ( storage_5_0_0.bit0.hold_mux B2 ) ( storage_5_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.qinv A ) ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.d ( storage_5_0_0.bit1.dmux0 Y ) ( storage_5_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.dhold ( storage_5_0_0.bit1.hold_mux Y ) ( storage_5_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.q ( storage_5_0_0.bit1.hold_mux B2 ) ( storage_5_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.qinv A ) ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.d ( storage_5_0_0.bit2.dmux0 Y ) ( storage_5_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.dhold ( storage_5_0_0.bit2.hold_mux Y ) ( storage_5_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.q ( storage_5_0_0.bit2.hold_mux B2 ) ( storage_5_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.qinv A ) ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.d ( storage_5_0_0.bit3.dmux0 Y ) ( storage_5_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.dhold ( storage_5_0_0.bit3.hold_mux Y ) ( storage_5_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.q ( storage_5_0_0.bit3.hold_mux B2 ) ( storage_5_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.qinv A ) ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.d ( storage_5_0_0.bit4.dmux0 Y ) ( storage_5_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.dhold ( storage_5_0_0.bit4.hold_mux Y ) ( storage_5_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.q ( storage_5_0_0.bit4.hold_mux B2 ) ( storage_5_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.qinv A ) ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.d ( storage_5_0_0.bit5.dmux0 Y ) ( storage_5_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.dhold ( storage_5_0_0.bit5.hold_mux Y ) ( storage_5_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.q ( storage_5_0_0.bit5.hold_mux B2 ) ( storage_5_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.qinv A ) ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.d ( storage_5_0_0.bit6.dmux0 Y ) ( storage_5_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.dhold ( storage_5_0_0.bit6.hold_mux Y ) ( storage_5_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.q ( storage_5_0_0.bit6.hold_mux B2 ) ( storage_5_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.qinv A ) ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.d ( storage_5_0_0.bit7.dmux0 Y ) ( storage_5_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.dhold ( storage_5_0_0.bit7.hold_mux Y ) ( storage_5_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.q ( storage_5_0_0.bit7.hold_mux B2 ) ( storage_5_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.qinv A ) ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.hold ( storage_5_0_0.bit7.hold_mux B1 ) ( storage_5_0_0.bit6.hold_mux B1 ) ( storage_5_0_0.bit5.hold_mux B1 ) ( storage_5_0_0.bit4.hold_mux B1 ) ( storage_5_0_0.bit3.hold_mux B1 ) ( storage_5_0_0.bit2.hold_mux B1 ) ( storage_5_0_0.bit1.hold_mux B1 ) ++ ( storage_5_0_0.bit0.hold_mux B1 ) ( storage_5_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.bit7.hold_mux A1 ) ( storage_5_0_0.bit6.hold_mux A1 ) ( storage_5_0_0.bit5.hold_mux A1 ) ( storage_5_0_0.bit4.hold_mux A1 ) ( storage_5_0_0.bit3.hold_mux A1 ) ( storage_5_0_0.bit2.hold_mux A1 ) ( storage_5_0_0.bit1.hold_mux A1 ) ++ ( storage_5_0_0.bit0.hold_mux A1 ) ( storage_5_0_0.any_or0 Y ) ( storage_5_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_5_0_0.we0 ( storage_5_0_0.bit7.dmux0 A1 ) ( storage_5_0_0.bit6.dmux0 A1 ) ( storage_5_0_0.bit5.dmux0 A1 ) ( storage_5_0_0.bit4.dmux0 A1 ) ( storage_5_0_0.bit3.dmux0 A1 ) ( storage_5_0_0.bit2.dmux0 A1 ) ( storage_5_0_0.bit1.dmux0 A1 ) ++ ( storage_5_0_0.bit0.dmux0 A1 ) ( storage_5_0_0.any_or0 B ) ( storage_5_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_5_0_0.we1 ( storage_5_0_0.bit7.dmux0 B1 ) ( storage_5_0_0.bit6.dmux0 B1 ) ( storage_5_0_0.bit5.dmux0 B1 ) ( storage_5_0_0.bit4.dmux0 B1 ) ( storage_5_0_0.bit3.dmux0 B1 ) ( storage_5_0_0.bit2.dmux0 B1 ) ( storage_5_0_0.bit1.dmux0 B1 ) ++ ( storage_5_0_0.bit0.dmux0 B1 ) ( storage_5_0_0.any_or0 A ) ( storage_5_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.d ( storage_6_0_0.bit0.dmux0 Y ) ( storage_6_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.dhold ( storage_6_0_0.bit0.hold_mux Y ) ( storage_6_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.q ( storage_6_0_0.bit0.hold_mux B2 ) ( storage_6_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.qinv A ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.d ( storage_6_0_0.bit1.dmux0 Y ) ( storage_6_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.dhold ( storage_6_0_0.bit1.hold_mux Y ) ( storage_6_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.q ( storage_6_0_0.bit1.hold_mux B2 ) ( storage_6_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.qinv A ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.d ( storage_6_0_0.bit2.dmux0 Y ) ( storage_6_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.dhold ( storage_6_0_0.bit2.hold_mux Y ) ( storage_6_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.q ( storage_6_0_0.bit2.hold_mux B2 ) ( storage_6_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.qinv A ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.d ( storage_6_0_0.bit3.dmux0 Y ) ( storage_6_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.dhold ( storage_6_0_0.bit3.hold_mux Y ) ( storage_6_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.q ( storage_6_0_0.bit3.hold_mux B2 ) ( storage_6_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.qinv A ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.d ( storage_6_0_0.bit4.dmux0 Y ) ( storage_6_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.dhold ( storage_6_0_0.bit4.hold_mux Y ) ( storage_6_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.q ( storage_6_0_0.bit4.hold_mux B2 ) ( storage_6_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.qinv A ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.d ( storage_6_0_0.bit5.dmux0 Y ) ( storage_6_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.dhold ( storage_6_0_0.bit5.hold_mux Y ) ( storage_6_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.q ( storage_6_0_0.bit5.hold_mux B2 ) ( storage_6_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.qinv A ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.d ( storage_6_0_0.bit6.dmux0 Y ) ( storage_6_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.dhold ( storage_6_0_0.bit6.hold_mux Y ) ( storage_6_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.q ( storage_6_0_0.bit6.hold_mux B2 ) ( storage_6_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.qinv A ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.d ( storage_6_0_0.bit7.dmux0 Y ) ( storage_6_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.dhold ( storage_6_0_0.bit7.hold_mux Y ) ( storage_6_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.q ( storage_6_0_0.bit7.hold_mux B2 ) ( storage_6_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.qinv A ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.hold ( storage_6_0_0.bit7.hold_mux B1 ) ( storage_6_0_0.bit6.hold_mux B1 ) ( storage_6_0_0.bit5.hold_mux B1 ) ( storage_6_0_0.bit4.hold_mux B1 ) ( storage_6_0_0.bit3.hold_mux B1 ) ( storage_6_0_0.bit2.hold_mux B1 ) ( storage_6_0_0.bit1.hold_mux B1 ) ++ ( storage_6_0_0.bit0.hold_mux B1 ) ( storage_6_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.bit7.hold_mux A1 ) ( storage_6_0_0.bit6.hold_mux A1 ) ( storage_6_0_0.bit5.hold_mux A1 ) ( storage_6_0_0.bit4.hold_mux A1 ) ( storage_6_0_0.bit3.hold_mux A1 ) ( storage_6_0_0.bit2.hold_mux A1 ) ( storage_6_0_0.bit1.hold_mux A1 ) ++ ( storage_6_0_0.bit0.hold_mux A1 ) ( storage_6_0_0.any_or0 Y ) ( storage_6_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_6_0_0.we0 ( storage_6_0_0.bit7.dmux0 A1 ) ( storage_6_0_0.bit6.dmux0 A1 ) ( storage_6_0_0.bit5.dmux0 A1 ) ( storage_6_0_0.bit4.dmux0 A1 ) ( storage_6_0_0.bit3.dmux0 A1 ) ( storage_6_0_0.bit2.dmux0 A1 ) ( storage_6_0_0.bit1.dmux0 A1 ) ++ ( storage_6_0_0.bit0.dmux0 A1 ) ( storage_6_0_0.any_or0 B ) ( storage_6_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_6_0_0.we1 ( storage_6_0_0.bit7.dmux0 B1 ) ( storage_6_0_0.bit6.dmux0 B1 ) ( storage_6_0_0.bit5.dmux0 B1 ) ( storage_6_0_0.bit4.dmux0 B1 ) ( storage_6_0_0.bit3.dmux0 B1 ) ( storage_6_0_0.bit2.dmux0 B1 ) ( storage_6_0_0.bit1.dmux0 B1 ) ++ ( storage_6_0_0.bit0.dmux0 B1 ) ( storage_6_0_0.any_or0 A ) ( storage_6_0_0.gcand1 Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.d ( storage_7_0_0.bit0.dmux0 Y ) ( storage_7_0_0.bit0.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.dhold ( storage_7_0_0.bit0.hold_mux Y ) ( storage_7_0_0.bit0.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.q ( storage_7_0_0.bit0.hold_mux B2 ) ( storage_7_0_0.bit0.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.qinv A ) ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.d ( storage_7_0_0.bit1.dmux0 Y ) ( storage_7_0_0.bit1.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.dhold ( storage_7_0_0.bit1.hold_mux Y ) ( storage_7_0_0.bit1.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.q ( storage_7_0_0.bit1.hold_mux B2 ) ( storage_7_0_0.bit1.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.qinv A ) ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.d ( storage_7_0_0.bit2.dmux0 Y ) ( storage_7_0_0.bit2.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.dhold ( storage_7_0_0.bit2.hold_mux Y ) ( storage_7_0_0.bit2.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.q ( storage_7_0_0.bit2.hold_mux B2 ) ( storage_7_0_0.bit2.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.qinv A ) ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.d ( storage_7_0_0.bit3.dmux0 Y ) ( storage_7_0_0.bit3.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.dhold ( storage_7_0_0.bit3.hold_mux Y ) ( storage_7_0_0.bit3.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.q ( storage_7_0_0.bit3.hold_mux B2 ) ( storage_7_0_0.bit3.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.qinv A ) ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.d ( storage_7_0_0.bit4.dmux0 Y ) ( storage_7_0_0.bit4.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.dhold ( storage_7_0_0.bit4.hold_mux Y ) ( storage_7_0_0.bit4.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.q ( storage_7_0_0.bit4.hold_mux B2 ) ( storage_7_0_0.bit4.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.qinv A ) ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.d ( storage_7_0_0.bit5.dmux0 Y ) ( storage_7_0_0.bit5.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.dhold ( storage_7_0_0.bit5.hold_mux Y ) ( storage_7_0_0.bit5.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.q ( storage_7_0_0.bit5.hold_mux B2 ) ( storage_7_0_0.bit5.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.qinv A ) ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.d ( storage_7_0_0.bit6.dmux0 Y ) ( storage_7_0_0.bit6.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.dhold ( storage_7_0_0.bit6.hold_mux Y ) ( storage_7_0_0.bit6.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.q ( storage_7_0_0.bit6.hold_mux B2 ) ( storage_7_0_0.bit6.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.qinv A ) ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.d ( storage_7_0_0.bit7.dmux0 Y ) ( storage_7_0_0.bit7.hold_mux A2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.dhold ( storage_7_0_0.bit7.hold_mux Y ) ( storage_7_0_0.bit7.bit D ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.q ( storage_7_0_0.bit7.hold_mux B2 ) ( storage_7_0_0.bit7.qinv Y ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.qinv A ) ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.hold ( storage_7_0_0.bit7.hold_mux B1 ) ( storage_7_0_0.bit6.hold_mux B1 ) ( storage_7_0_0.bit5.hold_mux B1 ) ( storage_7_0_0.bit4.hold_mux B1 ) ( storage_7_0_0.bit3.hold_mux B1 ) ( storage_7_0_0.bit2.hold_mux B1 ) ( storage_7_0_0.bit1.hold_mux B1 ) ++ ( storage_7_0_0.bit0.hold_mux B1 ) ( storage_7_0_0.hold_inv Y ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.bit7.hold_mux A1 ) ( storage_7_0_0.bit6.hold_mux A1 ) ( storage_7_0_0.bit5.hold_mux A1 ) ( storage_7_0_0.bit4.hold_mux A1 ) ( storage_7_0_0.bit3.hold_mux A1 ) ( storage_7_0_0.bit2.hold_mux A1 ) ( storage_7_0_0.bit1.hold_mux A1 ) ++ ( storage_7_0_0.bit0.hold_mux A1 ) ( storage_7_0_0.any_or0 Y ) ( storage_7_0_0.hold_inv A ) + USE SIGNAL ; ++ - storage_7_0_0.we0 ( storage_7_0_0.bit7.dmux0 A1 ) ( storage_7_0_0.bit6.dmux0 A1 ) ( storage_7_0_0.bit5.dmux0 A1 ) ( storage_7_0_0.bit4.dmux0 A1 ) ( storage_7_0_0.bit3.dmux0 A1 ) ( storage_7_0_0.bit2.dmux0 A1 ) ( storage_7_0_0.bit1.dmux0 A1 ) ++ ( storage_7_0_0.bit0.dmux0 A1 ) ( storage_7_0_0.any_or0 B ) ( storage_7_0_0.gcand0 Y ) + USE SIGNAL ; ++ - storage_7_0_0.we1 ( storage_7_0_0.bit7.dmux0 B1 ) ( storage_7_0_0.bit6.dmux0 B1 ) ( storage_7_0_0.bit5.dmux0 B1 ) ( storage_7_0_0.bit4.dmux0 B1 ) ( storage_7_0_0.bit3.dmux0 B1 ) ( storage_7_0_0.bit2.dmux0 B1 ) ( storage_7_0_0.bit1.dmux0 B1 ) ++ ( storage_7_0_0.bit0.dmux0 B1 ) ( storage_7_0_0.any_or0 A ) ( storage_7_0_0.gcand1 Y ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) ( storage_0_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand0 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w0 ( sel_buf_w_p1.sel_buf_0 Y ) ( storage_0_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w1 ( sel_buf_w_p1.sel_buf_1 Y ) ( storage_1_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w2 ( sel_buf_w_p1.sel_buf_2 Y ) ( storage_2_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w3 ( sel_buf_w_p1.sel_buf_3 Y ) ( storage_3_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w4 ( sel_buf_w_p1.sel_buf_4 Y ) ( storage_4_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w5 ( sel_buf_w_p1.sel_buf_5 Y ) ( storage_5_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w6 ( sel_buf_w_p1.sel_buf_6 Y ) ( storage_6_0_0.gcand1 A ) + USE SIGNAL ; ++ - w_sel_p1.select_w7 ( sel_buf_w_p1.sel_buf_7 Y ) ( storage_7_0_0.gcand1 A ) + USE SIGNAL ; ++ - we0[0] ( PIN we0[0] ) ( storage_7_0_0.gcand0 B ) ( storage_6_0_0.gcand0 B ) ( storage_5_0_0.gcand0 B ) ( storage_4_0_0.gcand0 B ) ( storage_3_0_0.gcand0 B ) ( storage_2_0_0.gcand0 B ) ++ ( storage_1_0_0.gcand0 B ) ( storage_0_0_0.gcand0 B ) + USE SIGNAL ; ++ - we1[0] ( PIN we1[0] ) ( storage_7_0_0.gcand1 B ) ( storage_6_0_0.gcand1 B ) ( storage_5_0_0.gcand1 B ) ( storage_4_0_0.gcand1 B ) ( storage_3_0_0.gcand1 B ) ( storage_2_0_0.gcand1 B ) ++ ( storage_1_0_0.gcand1 B ) ( storage_0_0_0.gcand1 B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r2w_or_asap7.tcl b/src/ram/test/make_8x8_2r2w_or_asap7.tcl +new file mode 100644 +index 0000000000..ec70f96878 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r2w_or_asap7.tcl +@@ -0,0 +1,35 @@ ++# generate_ram on asap7 with two write ports that, writing the same word ++# in one cycle, write the OR of their data (-write_priority or), as ++# firtool's register files merge their writes; each word holds by a mux ++# per bit (-write_style mux). ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r2w_or_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 2 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -write_style mux \ ++ -write_priority or \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r2w_or_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r2w_or_asap7.defok $def_file ++ ++diff_files make_8x8_2r2w_or_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r2w_or_asap7_behavioral.vok b/src/ram/test/make_8x8_2r2w_or_asap7_behavioral.vok +new file mode 100644 +index 0000000000..c44cea3bdd +--- /dev/null ++++ b/src/ram/test/make_8x8_2r2w_or_asap7_behavioral.vok +@@ -0,0 +1,54 @@ ++module RAM8x8 ( ++ clk, ++ D0, ++ D1, ++ Q0, ++ Q1, ++ addr_w0, ++ addr_w1, ++ addr_r0, ++ addr_r1, ++ we0, ++ we1 ++); ++ input clk; ++ input [7:0] D0; ++ input [7:0] D1; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w0; ++ input [2:0] addr_w1; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we0; ++ input [0:0] we1; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we0[i]) begin ++ mem[addr_w0][i*8 +:8] <= D0[i*8 +:8]; ++ end ++ end ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we1[i]) begin ++ mem[addr_w1][i*8 +:8] <= D1[i*8 +:8] ++ | ({8{we0[i] && addr_w0 == addr_w1}} & D0[i*8 +:8]); ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index 20fd131110..9ca6d25ce3 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -13,6 +13,7 @@ record_tests { + make_8x8_rb_asap7 + make_8x8_rb_latency_asap7 + make_8x8_2r1w_mux_asap7 ++ make_8x8_2r2w_or_asap7 + make_8x8_2r1w_unplaced_asap7 + make_8x8_latch_sky130 + } diff --git a/patches/0025-openroad-ram-service-columns.patch b/patches/0025-openroad-ram-service-columns.patch new file mode 100644 index 000000000..4d125709b --- /dev/null +++ b/patches/0025-openroad-ram-service-columns.patch @@ -0,0 +1,1013 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -service_columns, room in the array + +-service_columns {every sites} puts an empty column `sites` sites wide +after every `every` storage columns. An array of placed standard cells +is full: a parent flow that buffers the long nets crossing it (repair +inserts wire buffers on the word selects and read bitlines) has no site +to put them on, and legalization fails. XiangShan's RobEntryFile, +352 words of 21 bits with 16 read and 8 write ports, dissolved into a +parent, left 1,230 such buffers overlapping without these columns. The +columns are inside the core, so -periphery unplaced keeps them in the +outline. Default: none, as before. + +The fifteenth of the generate_regfile features carried onto +generate_ram (its tap_columns and service_sites); see OpenROAD #11669. +Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index 1ab0b488f4..c0d4089d01 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -53,6 +53,7 @@ generate_ram [-mask_size bits] + [-read_latency 0|1] + [-write_style clock_gate|mux] + [-write_priority last|or] ++ [-service_columns {every sites}] + [-cells {role master ...}] + [-name name] + [-decoder row|word] +@@ -89,6 +90,7 @@ generate_ram [-mask_size bits] + | `-read_latency` | `1` registers every read port's address, a plain positive-edge flop per address bit, so the data follows a cycle after the address. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. | + | `-write_style` | How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock. Not with `-use_latch`. Default: `clock_gate`. | + | `-write_priority` | Where two write ports write the same word in one cycle: `last`, the last port's data; or `or`, the OR of every writing port's data, as RTL that merges its writes with an OR describes it (firtool's register files). `or` drops a word's priority logic, an inverter and an AND2 per port but the last. Default: `last`. | ++| `-service_columns {every sites}` | An empty column `sites` sites wide after every `every` storage columns: room inside the array for the buffers a parent flow inserts on the long nets that cross it, where the array is otherwise full. Default: none. | + | `-periphery`, `-pin_layer` | `generate_ram_netlist` only. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. Default: `placed`. | + | `-cells` | The cell for a role (`inv`, `and2`, `buffer`, `clock_gate`, `aoi22`, `ao22`, `or2`, `nand2`, `nor2`, `tie`, `addr_flop`), instead of the smallest the libraries have of its function. An AOI22 or AO22 given is checked by its truth table. Default: the smallest of each. | + | `-name` | The block's and the behavioral model's name. Default: `RAMx`. | +diff --git a/src/ram/include/ram/layout.h b/src/ram/include/ram/layout.h +index bbaf4b7abd..b8a5cf072e 100644 +--- a/src/ram/include/ram/layout.h ++++ b/src/ram/include/ram/layout.h +@@ -65,6 +65,9 @@ class Layout + + int getWidth() const; + ++ // a floor on the width, for a column kept empty ++ void setMinWidth(int width); ++ + private: + odb::Orientation2D orientation_; + odb::Point origin_; +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index ffb19bcdd6..cecaf6716f 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -126,7 +126,9 @@ class RamGen + const std::string& name = "", + const std::string& decoder = "row", + int bit_folds = 1, +- const std::string& wrapper_verilog = ""); ++ const std::string& wrapper_verilog = "", ++ int service_every = 0, ++ int service_sites = 0); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +diff --git a/src/ram/src/layout.cpp b/src/ram/src/layout.cpp +index 4a75649c5a..41b3ea57bf 100644 +--- a/src/ram/src/layout.cpp ++++ b/src/ram/src/layout.cpp +@@ -148,6 +148,11 @@ int Layout::getWidth() const + return cell_width_; + } + ++void Layout::setMinWidth(const int width) ++{ ++ cell_width_ = std::max(cell_width_, width); ++} ++ + ////////////////////////////////////////////////////////////// + + Grid::Grid(odb::Orientation2D orientation) : orientation_(orientation) +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 950f185239..0bb65688bb 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -1958,7 +1958,9 @@ void RamGen::generate(const int mask_size, + const std::string& name, + const std::string& decoder, + const int bit_folds, +- const std::string& wrapper_verilog) ++ const std::string& wrapper_verilog, ++ const int service_every, ++ const int service_sites) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -3081,6 +3083,22 @@ void RamGen::generate(const int mask_size, + ram_grid_.setOrigin(ram_origin); + ram_grid_.gridInit(); + ++ // -service_columns {every sites}: after every `every` storage columns ++ // an empty column `sites` sites wide, room a parent's buffers can take ++ // inside the array ++ if (service_every > 0 && service_sites > 0) { ++ const int site_width ++ = (*(*db_->getLibs().begin())->getSites().begin())->getWidth(); ++ for (int col = (col_cell_count - 1) / service_every * service_every; ++ col > 0; ++ col -= service_every) { ++ auto service = std::make_unique(odb::vertical); ++ service->setMinWidth(service_sites * site_width); ++ ram_grid_.insertLayout(std::move(service), col); ++ } ++ ram_grid_.gridInit(); ++ } ++ + if (tapcell_) { + // max tap distance specified is greater than the length of ram + if (ram_grid_.getRowWidth() <= max_tap_dist) { +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index 429ae8b763..b70e571e2f 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -58,7 +58,9 @@ generate_ram_netlist_cmd(int mask_size, + const char* name, + const char* decoder, + const int bit_folds, +- const char* wrapper_verilog) ++ const char* wrapper_verilog, ++ const int service_every, ++ const int service_sites) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -113,7 +115,8 @@ generate_ram_netlist_cmd(int mask_size, + tapcell, max_tap_dist, read_style, zero_word, + reset_value, banks, bank_columns, bank_order, rb_ports, + read_latency, write_style, write_priority, periphery, pin_layer, cells, +- name, decoder, bit_folds, wrapper_verilog); ++ name, decoder, bit_folds, wrapper_verilog, ++ service_every, service_sites); + } + + void ram_pdngen(const char* power_net_name, const char* ground_net_name, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index b40dd4616f..df0de59aae 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -37,6 +37,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-name name] + [-decoder row|word] + [-bit_folds count] ++ [-service_columns {every sites}] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -51,7 +52,7 @@ proc generate_ram_netlist { args } { + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority +- -periphery -pin_layer -cells -name -decoder -bit_folds -wrapper_verilog } flags {} ++ -periphery -pin_layer -cells -name -decoder -bit_folds -wrapper_verilog -service_columns } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -233,6 +234,17 @@ proc generate_ram_netlist { args } { + # column mux selecting within it; or word, a balanced AND2 tree over + # each word's whole address. + # A word's mask slices in this many rows instead of side by side. ++ # Empty columns in the array for a parent's buffers: one `sites` sites ++ # wide after every `every` storage columns. ++ set service_every 0 ++ set service_sites 0 ++ if { [info exists keys(-service_columns)] } { ++ if { [llength $keys(-service_columns)] != 2 } { ++ utl::error RAM 89 "-service_columns is {every sites}." ++ } ++ lassign $keys(-service_columns) service_every service_sites ++ } ++ + set bit_folds 1 + if { [info exists keys(-bit_folds)] } { + set bit_folds $keys(-bit_folds) +@@ -288,7 +300,7 @@ proc generate_ram_netlist { args } { + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ + $rb_ports $read_latency $write_style $write_priority $periphery $pin_layer $cells $name \ +- $decoder $bit_folds $wrapper_verilog ++ $decoder $bit_folds $wrapper_verilog $service_every $service_sites + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -324,7 +336,7 @@ proc generate_ram { args } { + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority +- -cells -name -decoder -bit_folds } flags {} ++ -cells -name -decoder -bit_folds -service_columns } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -374,7 +386,7 @@ proc generate_ram { args } { + } + + foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority +- -cells -name -decoder -bit_folds} { ++ -cells -name -decoder -bit_folds -service_columns} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 602b9c13f3..2ac84e6040 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -16,6 +16,7 @@ PASSFAIL_TESTS = [ + "make_8x8_2r1w_unplaced_asap7", + "make_8x8_2r1w_mux_asap7", + "make_8x8_2r2w_or_asap7", ++ "make_8x8_2r1w_service_asap7", + "make_8x8_rb_latency_asap7", + "make_8x8_rb_asap7", + "make_8x8_2r1w_banks_asap7", +@@ -91,6 +92,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_mux_asap7_behavioral.vok", + ], ++ "make_8x8_2r1w_service_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_service_asap7_behavioral.vok", ++ ], + "make_8x8_2r2w_or_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_service_asap7.defok b/src/ram/test/make_8x8_2r1w_service_asap7.defok +new file mode 100644 +index 0000000000..a67b8f3e3f +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_service_asap7.defok +@@ -0,0 +1,672 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 1911 243 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW5 asap7sc7p5t 0 135 FS DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW6 asap7sc7p5t 0 162 N DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW7 asap7sc7p5t 0 189 FS DO 354 BY 1 STEP 5 0 ; ++ROW RAM_ROW8 asap7sc7p5t 0 216 N DO 354 BY 1 STEP 5 0 ; ++COMPONENTS 281 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 216 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 172 216 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 345 216 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 518 216 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 745 216 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 918 216 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1090 216 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 1263 216 ) N ; ++ - decoder_p0.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1641 0 ) N ; ++ - decoder_p0.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1641 27 ) FS ; ++ - decoder_p0.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1641 54 ) N ; ++ - decoder_p0.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1641 81 ) FS ; ++ - decoder_p0.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1641 108 ) N ; ++ - decoder_p0.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1641 135 ) FS ; ++ - decoder_p0.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1641 162 ) N ; ++ - decoder_p0.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1641 189 ) FS ; ++ - decoder_p0.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1674 0 ) N ; ++ - decoder_p0.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1674 27 ) FS ; ++ - decoder_p0.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1674 54 ) N ; ++ - decoder_p0.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1674 81 ) FS ; ++ - decoder_p0.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1674 108 ) N ; ++ - decoder_p0.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1674 135 ) FS ; ++ - decoder_p0.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1674 162 ) N ; ++ - decoder_p0.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1674 189 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 1879 108 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 1879 54 ) N ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 1879 0 ) N ; ++ - decoder_p1.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1728 0 ) N ; ++ - decoder_p1.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1728 27 ) FS ; ++ - decoder_p1.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1728 54 ) N ; ++ - decoder_p1.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1728 81 ) FS ; ++ - decoder_p1.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1728 108 ) N ; ++ - decoder_p1.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1728 135 ) FS ; ++ - decoder_p1.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1728 162 ) N ; ++ - decoder_p1.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1728 189 ) FS ; ++ - decoder_p1.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1760 0 ) N ; ++ - decoder_p1.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1760 27 ) FS ; ++ - decoder_p1.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1760 54 ) N ; ++ - decoder_p1.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1760 81 ) FS ; ++ - decoder_p1.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1760 108 ) N ; ++ - decoder_p1.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1760 135 ) FS ; ++ - decoder_p1.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1760 162 ) N ; ++ - decoder_p1.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1760 189 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 1879 135 ) FS ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 1879 81 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 1879 27 ) FS ; ++ - decoder_p2.and_layer0_word0 AND2x2_ASAP7_75t_R + PLACED ( 1814 0 ) N ; ++ - decoder_p2.and_layer0_word1 AND2x2_ASAP7_75t_R + PLACED ( 1814 27 ) FS ; ++ - decoder_p2.and_layer0_word2 AND2x2_ASAP7_75t_R + PLACED ( 1814 54 ) N ; ++ - decoder_p2.and_layer0_word3 AND2x2_ASAP7_75t_R + PLACED ( 1814 81 ) FS ; ++ - decoder_p2.and_layer0_word4 AND2x2_ASAP7_75t_R + PLACED ( 1814 108 ) N ; ++ - decoder_p2.and_layer0_word5 AND2x2_ASAP7_75t_R + PLACED ( 1814 135 ) FS ; ++ - decoder_p2.and_layer0_word6 AND2x2_ASAP7_75t_R + PLACED ( 1814 162 ) N ; ++ - decoder_p2.and_layer0_word7 AND2x2_ASAP7_75t_R + PLACED ( 1814 189 ) FS ; ++ - decoder_p2.and_layer1_word0 AND2x2_ASAP7_75t_R + PLACED ( 1846 0 ) N ; ++ - decoder_p2.and_layer1_word1 AND2x2_ASAP7_75t_R + PLACED ( 1846 27 ) FS ; ++ - decoder_p2.and_layer1_word2 AND2x2_ASAP7_75t_R + PLACED ( 1846 54 ) N ; ++ - decoder_p2.and_layer1_word3 AND2x2_ASAP7_75t_R + PLACED ( 1846 81 ) FS ; ++ - decoder_p2.and_layer1_word4 AND2x2_ASAP7_75t_R + PLACED ( 1846 108 ) N ; ++ - decoder_p2.and_layer1_word5 AND2x2_ASAP7_75t_R + PLACED ( 1846 135 ) FS ; ++ - decoder_p2.and_layer1_word6 AND2x2_ASAP7_75t_R + PLACED ( 1846 162 ) N ; ++ - decoder_p2.and_layer1_word7 AND2x2_ASAP7_75t_R + PLACED ( 1846 189 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 1895 108 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 1895 54 ) N ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 1895 0 ) N ; ++ - read_w0_p0_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 0 ) N ; ++ - read_w0_p0_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_w0_p0_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 108 108 ) N ; ++ - read_w0_p0_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 108 162 ) N ; ++ - read_w0_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_w0_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 108 135 ) FS ; ++ - read_w0_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_w0_p0_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 280 0 ) N ; ++ - read_w0_p0_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_w0_p0_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 280 108 ) N ; ++ - read_w0_p0_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 280 162 ) N ; ++ - read_w0_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_w0_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 280 135 ) FS ; ++ - read_w0_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 280 81 ) FS ; ++ - read_w0_p0_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 0 ) N ; ++ - read_w0_p0_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_w0_p0_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 453 108 ) N ; ++ - read_w0_p0_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 453 162 ) N ; ++ - read_w0_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_w0_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 453 135 ) FS ; ++ - read_w0_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_w0_p0_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 626 0 ) N ; ++ - read_w0_p0_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_w0_p0_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 626 108 ) N ; ++ - read_w0_p0_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 626 162 ) N ; ++ - read_w0_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_w0_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 626 135 ) FS ; ++ - read_w0_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 626 81 ) FS ; ++ - read_w0_p0_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 853 0 ) N ; ++ - read_w0_p0_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 853 54 ) N ; ++ - read_w0_p0_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 853 108 ) N ; ++ - read_w0_p0_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 853 162 ) N ; ++ - read_w0_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 853 27 ) FS ; ++ - read_w0_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 853 135 ) FS ; ++ - read_w0_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 853 81 ) FS ; ++ - read_w0_p0_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1026 0 ) N ; ++ - read_w0_p0_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1026 54 ) N ; ++ - read_w0_p0_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1026 108 ) N ; ++ - read_w0_p0_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1026 162 ) N ; ++ - read_w0_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1026 27 ) FS ; ++ - read_w0_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1026 135 ) FS ; ++ - read_w0_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1026 81 ) FS ; ++ - read_w0_p0_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 0 ) N ; ++ - read_w0_p0_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 54 ) N ; ++ - read_w0_p0_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 108 ) N ; ++ - read_w0_p0_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1198 162 ) N ; ++ - read_w0_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1198 27 ) FS ; ++ - read_w0_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1198 135 ) FS ; ++ - read_w0_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1198 81 ) FS ; ++ - read_w0_p0_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 0 ) N ; ++ - read_w0_p0_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 54 ) N ; ++ - read_w0_p0_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 108 ) N ; ++ - read_w0_p0_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1371 162 ) N ; ++ - read_w0_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1371 27 ) FS ; ++ - read_w0_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1371 135 ) FS ; ++ - read_w0_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1371 81 ) FS ; ++ - read_w0_p1_b0.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 0 ) N ; ++ - read_w0_p1_b0.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_w0_p1_b0.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 140 108 ) N ; ++ - read_w0_p1_b0.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 140 162 ) N ; ++ - read_w0_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 129 27 ) FS ; ++ - read_w0_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 129 135 ) FS ; ++ - read_w0_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 129 81 ) FS ; ++ - read_w0_p1_b1.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 313 0 ) N ; ++ - read_w0_p1_b1.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_w0_p1_b1.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 313 108 ) N ; ++ - read_w0_p1_b1.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 313 162 ) N ; ++ - read_w0_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 302 27 ) FS ; ++ - read_w0_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 302 135 ) FS ; ++ - read_w0_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 302 81 ) FS ; ++ - read_w0_p1_b2.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 0 ) N ; ++ - read_w0_p1_b2.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_w0_p1_b2.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 486 108 ) N ; ++ - read_w0_p1_b2.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 486 162 ) N ; ++ - read_w0_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - read_w0_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 475 135 ) FS ; ++ - read_w0_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - read_w0_p1_b3.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 658 0 ) N ; ++ - read_w0_p1_b3.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_w0_p1_b3.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 658 108 ) N ; ++ - read_w0_p1_b3.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 658 162 ) N ; ++ - read_w0_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_w0_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 648 135 ) FS ; ++ - read_w0_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 648 81 ) FS ; ++ - read_w0_p1_b4.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 885 0 ) N ; ++ - read_w0_p1_b4.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 885 54 ) N ; ++ - read_w0_p1_b4.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 885 108 ) N ; ++ - read_w0_p1_b4.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 885 162 ) N ; ++ - read_w0_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 874 27 ) FS ; ++ - read_w0_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 874 135 ) FS ; ++ - read_w0_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 874 81 ) FS ; ++ - read_w0_p1_b5.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1058 0 ) N ; ++ - read_w0_p1_b5.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1058 54 ) N ; ++ - read_w0_p1_b5.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1058 108 ) N ; ++ - read_w0_p1_b5.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1058 162 ) N ; ++ - read_w0_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1047 27 ) FS ; ++ - read_w0_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1047 135 ) FS ; ++ - read_w0_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1047 81 ) FS ; ++ - read_w0_p1_b6.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1231 0 ) N ; ++ - read_w0_p1_b6.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1231 54 ) N ; ++ - read_w0_p1_b6.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1231 108 ) N ; ++ - read_w0_p1_b6.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1231 162 ) N ; ++ - read_w0_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1220 27 ) FS ; ++ - read_w0_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1220 135 ) FS ; ++ - read_w0_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1220 81 ) FS ; ++ - read_w0_p1_b7.aoi_r0 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 0 ) N ; ++ - read_w0_p1_b7.aoi_r2 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 54 ) N ; ++ - read_w0_p1_b7.aoi_r4 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 108 ) N ; ++ - read_w0_p1_b7.aoi_r6 AOI22xp33_ASAP7_75t_R + PLACED ( 1404 162 ) N ; ++ - read_w0_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1393 27 ) FS ; ++ - read_w0_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1393 135 ) FS ; ++ - read_w0_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1393 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1706 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1706 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1706 54 ) N ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1706 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1706 108 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1706 135 ) FS ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1706 162 ) N ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1706 189 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1792 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1792 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1792 54 ) N ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1792 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1792 108 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1792 135 ) FS ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1792 162 ) N ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1792 189 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 1620 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 1620 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 1620 54 ) N ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 1620 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 1620 108 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 1620 135 ) FS ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 1620 162 ) N ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 1620 189 ) FS ; ++ - storage_0_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - storage_0_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - storage_0_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - storage_0_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - storage_0_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 0 ) N ; ++ - storage_0_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 0 ) N ; ++ - storage_0_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 0 ) N ; ++ - storage_0_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 0 ) N ; ++ - storage_0_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 0 ) N ; ++ - storage_0_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 81 ) FS ; ++ - storage_4_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - storage_4_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - storage_4_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - storage_4_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 108 ) N ; ++ - storage_4_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 108 ) N ; ++ - storage_4_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 108 ) N ; ++ - storage_4_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 108 ) N ; ++ - storage_4_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 108 ) N ; ++ - storage_4_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 108 ) N ; ++ - storage_4_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 108 ) N ; ++ - storage_5_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 135 ) FS ; ++ - storage_5_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 135 ) FS ; ++ - storage_5_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 135 ) FS ; ++ - storage_5_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 135 ) FS ; ++ - storage_5_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 135 ) FS ; ++ - storage_5_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 135 ) FS ; ++ - storage_5_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 135 ) FS ; ++ - storage_5_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 135 ) FS ; ++ - storage_5_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 135 ) FS ; ++ - storage_5_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 135 ) FS ; ++ - storage_6_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 162 ) N ; ++ - storage_6_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 162 ) N ; ++ - storage_6_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 162 ) N ; ++ - storage_6_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 162 ) N ; ++ - storage_6_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 162 ) N ; ++ - storage_6_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 162 ) N ; ++ - storage_6_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 162 ) N ; ++ - storage_6_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 162 ) N ; ++ - storage_6_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 162 ) N ; ++ - storage_6_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 162 ) N ; ++ - storage_7_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 189 ) FS ; ++ - storage_7_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 189 ) FS ; ++ - storage_7_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 189 ) FS ; ++ - storage_7_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 189 ) FS ; ++ - storage_7_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 745 189 ) FS ; ++ - storage_7_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 918 189 ) FS ; ++ - storage_7_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1090 189 ) FS ; ++ - storage_7_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1263 189 ) FS ; ++ - storage_7_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1490 189 ) FS ; ++ - storage_7_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1587 189 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 300 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_7_0_0.bit0.bit D ) ( storage_6_0_0.bit0.bit D ) ( storage_5_0_0.bit0.bit D ) ( storage_4_0_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ++ ( storage_1_0_0.bit0.bit D ) ( storage_0_0_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_7_0_0.bit1.bit D ) ( storage_6_0_0.bit1.bit D ) ( storage_5_0_0.bit1.bit D ) ( storage_4_0_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ++ ( storage_1_0_0.bit1.bit D ) ( storage_0_0_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_7_0_0.bit2.bit D ) ( storage_6_0_0.bit2.bit D ) ( storage_5_0_0.bit2.bit D ) ( storage_4_0_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ++ ( storage_1_0_0.bit2.bit D ) ( storage_0_0_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_7_0_0.bit3.bit D ) ( storage_6_0_0.bit3.bit D ) ( storage_5_0_0.bit3.bit D ) ( storage_4_0_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ++ ( storage_1_0_0.bit3.bit D ) ( storage_0_0_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_7_0_0.bit4.bit D ) ( storage_6_0_0.bit4.bit D ) ( storage_5_0_0.bit4.bit D ) ( storage_4_0_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ++ ( storage_1_0_0.bit4.bit D ) ( storage_0_0_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_7_0_0.bit5.bit D ) ( storage_6_0_0.bit5.bit D ) ( storage_5_0_0.bit5.bit D ) ( storage_4_0_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ++ ( storage_1_0_0.bit5.bit D ) ( storage_0_0_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_7_0_0.bit6.bit D ) ( storage_6_0_0.bit6.bit D ) ( storage_5_0_0.bit6.bit D ) ( storage_4_0_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ++ ( storage_1_0_0.bit6.bit D ) ( storage_0_0_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_7_0_0.bit7.bit D ) ( storage_6_0_0.bit7.bit D ) ( storage_5_0_0.bit7.bit D ) ( storage_4_0_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ++ ( storage_1_0_0.bit7.bit D ) ( storage_0_0_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_w0_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_w0_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_w0_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_w0_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_w0_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_w0_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_w0_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_w0_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_w0_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_w0_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_w0_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_w0_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_w0_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_w0_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_w0_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_w0_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and_layer0_word6 A ) ( decoder_p1.and_layer0_word4 A ) ( decoder_p1.and_layer0_word2 A ) ( decoder_p1.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and_layer1_word5 A ) ( decoder_p1.and_layer1_word4 A ) ( decoder_p1.and_layer1_word1 A ) ( decoder_p1.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and_layer1_word3 B ) ( decoder_p1.and_layer1_word2 B ) ( decoder_p1.and_layer1_word1 B ) ( decoder_p1.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and_layer0_word7 A ) ( decoder_p1.and_layer0_word5 A ) ( decoder_p1.and_layer0_word3 A ) ( decoder_p1.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and_layer1_word7 A ) ( decoder_p1.and_layer1_word6 A ) ( decoder_p1.and_layer1_word3 A ) ( decoder_p1.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and_layer1_word7 B ) ( decoder_p1.and_layer1_word6 B ) ( decoder_p1.and_layer1_word5 B ) ( decoder_p1.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and_layer0_word6 A ) ( decoder_p2.and_layer0_word4 A ) ( decoder_p2.and_layer0_word2 A ) ( decoder_p2.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and_layer1_word5 A ) ( decoder_p2.and_layer1_word4 A ) ( decoder_p2.and_layer1_word1 A ) ( decoder_p2.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and_layer1_word3 B ) ( decoder_p2.and_layer1_word2 B ) ( decoder_p2.and_layer1_word1 B ) ( decoder_p2.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and_layer0_word7 A ) ( decoder_p2.and_layer0_word5 A ) ( decoder_p2.and_layer0_word3 A ) ( decoder_p2.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and_layer1_word7 A ) ( decoder_p2.and_layer1_word6 A ) ( decoder_p2.and_layer1_word3 A ) ( decoder_p2.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and_layer1_word7 B ) ( decoder_p2.and_layer1_word6 B ) ( decoder_p2.and_layer1_word5 B ) ( decoder_p2.and_layer1_word4 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and_layer0_word6 A ) ( decoder_p0.and_layer0_word4 A ) ( decoder_p0.and_layer0_word2 A ) ( decoder_p0.and_layer0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and_layer1_word5 A ) ( decoder_p0.and_layer1_word4 A ) ( decoder_p0.and_layer1_word1 A ) ( decoder_p0.and_layer1_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and_layer1_word3 B ) ( decoder_p0.and_layer1_word2 B ) ( decoder_p0.and_layer1_word1 B ) ( decoder_p0.and_layer1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and_layer0_word7 A ) ( decoder_p0.and_layer0_word5 A ) ( decoder_p0.and_layer0_word3 A ) ( decoder_p0.and_layer0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and_layer1_word7 A ) ( decoder_p0.and_layer1_word6 A ) ( decoder_p0.and_layer1_word3 A ) ( decoder_p0.and_layer1_word2 A ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and_layer1_word7 B ) ( decoder_p0.and_layer1_word6 B ) ( decoder_p0.and_layer1_word5 B ) ( decoder_p0.and_layer1_word4 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_7_0_0.cg CLK ) ( storage_6_0_0.cg CLK ) ( storage_5_0_0.cg CLK ) ( storage_4_0_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_0_0.cg CLK ) ++ ( storage_1_0_0.cg CLK ) ( storage_0_0_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word0 ( decoder_p0.and_layer1_word0 Y ) ( decoder_p0.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word1 ( decoder_p0.and_layer1_word1 Y ) ( decoder_p0.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word2 ( decoder_p0.and_layer1_word2 Y ) ( decoder_p0.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word3 ( decoder_p0.and_layer1_word3 Y ) ( decoder_p0.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word4 ( decoder_p0.and_layer1_word4 Y ) ( decoder_p0.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word5 ( decoder_p0.and_layer1_word5 Y ) ( decoder_p0.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word6 ( decoder_p0.and_layer1_word6 Y ) ( decoder_p0.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p0.layer_in0_word7 ( decoder_p0.and_layer1_word7 Y ) ( decoder_p0.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and_layer0_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and_layer0_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and_layer0_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and_layer0_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and_layer0_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and_layer0_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and_layer0_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and_layer0_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word0 ( decoder_p1.and_layer1_word0 Y ) ( decoder_p1.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word1 ( decoder_p1.and_layer1_word1 Y ) ( decoder_p1.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word2 ( decoder_p1.and_layer1_word2 Y ) ( decoder_p1.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word3 ( decoder_p1.and_layer1_word3 Y ) ( decoder_p1.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word4 ( decoder_p1.and_layer1_word4 Y ) ( decoder_p1.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word5 ( decoder_p1.and_layer1_word5 Y ) ( decoder_p1.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word6 ( decoder_p1.and_layer1_word6 Y ) ( decoder_p1.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p1.layer_in0_word7 ( decoder_p1.and_layer1_word7 Y ) ( decoder_p1.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and_layer0_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and_layer0_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and_layer0_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and_layer0_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and_layer0_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and_layer0_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and_layer0_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and_layer0_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word0 ( decoder_p2.and_layer1_word0 Y ) ( decoder_p2.and_layer0_word0 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word1 ( decoder_p2.and_layer1_word1 Y ) ( decoder_p2.and_layer0_word1 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word2 ( decoder_p2.and_layer1_word2 Y ) ( decoder_p2.and_layer0_word2 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word3 ( decoder_p2.and_layer1_word3 Y ) ( decoder_p2.and_layer0_word3 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word4 ( decoder_p2.and_layer1_word4 Y ) ( decoder_p2.and_layer0_word4 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word5 ( decoder_p2.and_layer1_word5 Y ) ( decoder_p2.and_layer0_word5 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word6 ( decoder_p2.and_layer1_word6 Y ) ( decoder_p2.and_layer0_word6 B ) + USE SIGNAL ; ++ - decoder_p2.layer_in0_word7 ( decoder_p2.and_layer1_word7 Y ) ( decoder_p2.and_layer0_word7 B ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and_layer0_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and_layer0_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and_layer0_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and_layer0_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and_layer0_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and_layer0_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and_layer0_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and_layer0_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_w0_p0_b7.aoi_r0 A1 ) ( read_w0_p0_b6.aoi_r0 A1 ) ( read_w0_p0_b5.aoi_r0 A1 ) ( read_w0_p0_b4.aoi_r0 A1 ) ( read_w0_p0_b3.aoi_r0 A1 ) ( read_w0_p0_b2.aoi_r0 A1 ) ++ ( read_w0_p0_b1.aoi_r0 A1 ) ( read_w0_p0_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_w0_p0_b7.aoi_r0 B1 ) ( read_w0_p0_b6.aoi_r0 B1 ) ( read_w0_p0_b5.aoi_r0 B1 ) ( read_w0_p0_b4.aoi_r0 B1 ) ( read_w0_p0_b3.aoi_r0 B1 ) ( read_w0_p0_b2.aoi_r0 B1 ) ++ ( read_w0_p0_b1.aoi_r0 B1 ) ( read_w0_p0_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_w0_p0_b7.aoi_r2 A1 ) ( read_w0_p0_b6.aoi_r2 A1 ) ( read_w0_p0_b5.aoi_r2 A1 ) ( read_w0_p0_b4.aoi_r2 A1 ) ( read_w0_p0_b3.aoi_r2 A1 ) ( read_w0_p0_b2.aoi_r2 A1 ) ++ ( read_w0_p0_b1.aoi_r2 A1 ) ( read_w0_p0_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_w0_p0_b7.aoi_r2 B1 ) ( read_w0_p0_b6.aoi_r2 B1 ) ( read_w0_p0_b5.aoi_r2 B1 ) ( read_w0_p0_b4.aoi_r2 B1 ) ( read_w0_p0_b3.aoi_r2 B1 ) ( read_w0_p0_b2.aoi_r2 B1 ) ++ ( read_w0_p0_b1.aoi_r2 B1 ) ( read_w0_p0_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_w0_p0_b7.aoi_r4 A1 ) ( read_w0_p0_b6.aoi_r4 A1 ) ( read_w0_p0_b5.aoi_r4 A1 ) ( read_w0_p0_b4.aoi_r4 A1 ) ( read_w0_p0_b3.aoi_r4 A1 ) ( read_w0_p0_b2.aoi_r4 A1 ) ++ ( read_w0_p0_b1.aoi_r4 A1 ) ( read_w0_p0_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_w0_p0_b7.aoi_r4 B1 ) ( read_w0_p0_b6.aoi_r4 B1 ) ( read_w0_p0_b5.aoi_r4 B1 ) ( read_w0_p0_b4.aoi_r4 B1 ) ( read_w0_p0_b3.aoi_r4 B1 ) ( read_w0_p0_b2.aoi_r4 B1 ) ++ ( read_w0_p0_b1.aoi_r4 B1 ) ( read_w0_p0_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_w0_p0_b7.aoi_r6 A1 ) ( read_w0_p0_b6.aoi_r6 A1 ) ( read_w0_p0_b5.aoi_r6 A1 ) ( read_w0_p0_b4.aoi_r6 A1 ) ( read_w0_p0_b3.aoi_r6 A1 ) ( read_w0_p0_b2.aoi_r6 A1 ) ++ ( read_w0_p0_b1.aoi_r6 A1 ) ( read_w0_p0_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_w0_p0_b7.aoi_r6 B1 ) ( read_w0_p0_b6.aoi_r6 B1 ) ( read_w0_p0_b5.aoi_r6 B1 ) ( read_w0_p0_b4.aoi_r6 B1 ) ( read_w0_p0_b3.aoi_r6 B1 ) ( read_w0_p0_b2.aoi_r6 B1 ) ++ ( read_w0_p0_b1.aoi_r6 B1 ) ( read_w0_p0_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_w0_p1_b7.aoi_r0 A1 ) ( read_w0_p1_b6.aoi_r0 A1 ) ( read_w0_p1_b5.aoi_r0 A1 ) ( read_w0_p1_b4.aoi_r0 A1 ) ( read_w0_p1_b3.aoi_r0 A1 ) ( read_w0_p1_b2.aoi_r0 A1 ) ++ ( read_w0_p1_b1.aoi_r0 A1 ) ( read_w0_p1_b0.aoi_r0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_w0_p1_b7.aoi_r0 B1 ) ( read_w0_p1_b6.aoi_r0 B1 ) ( read_w0_p1_b5.aoi_r0 B1 ) ( read_w0_p1_b4.aoi_r0 B1 ) ( read_w0_p1_b3.aoi_r0 B1 ) ( read_w0_p1_b2.aoi_r0 B1 ) ++ ( read_w0_p1_b1.aoi_r0 B1 ) ( read_w0_p1_b0.aoi_r0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_w0_p1_b7.aoi_r2 A1 ) ( read_w0_p1_b6.aoi_r2 A1 ) ( read_w0_p1_b5.aoi_r2 A1 ) ( read_w0_p1_b4.aoi_r2 A1 ) ( read_w0_p1_b3.aoi_r2 A1 ) ( read_w0_p1_b2.aoi_r2 A1 ) ++ ( read_w0_p1_b1.aoi_r2 A1 ) ( read_w0_p1_b0.aoi_r2 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_w0_p1_b7.aoi_r2 B1 ) ( read_w0_p1_b6.aoi_r2 B1 ) ( read_w0_p1_b5.aoi_r2 B1 ) ( read_w0_p1_b4.aoi_r2 B1 ) ( read_w0_p1_b3.aoi_r2 B1 ) ( read_w0_p1_b2.aoi_r2 B1 ) ++ ( read_w0_p1_b1.aoi_r2 B1 ) ( read_w0_p1_b0.aoi_r2 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_w0_p1_b7.aoi_r4 A1 ) ( read_w0_p1_b6.aoi_r4 A1 ) ( read_w0_p1_b5.aoi_r4 A1 ) ( read_w0_p1_b4.aoi_r4 A1 ) ( read_w0_p1_b3.aoi_r4 A1 ) ( read_w0_p1_b2.aoi_r4 A1 ) ++ ( read_w0_p1_b1.aoi_r4 A1 ) ( read_w0_p1_b0.aoi_r4 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_w0_p1_b7.aoi_r4 B1 ) ( read_w0_p1_b6.aoi_r4 B1 ) ( read_w0_p1_b5.aoi_r4 B1 ) ( read_w0_p1_b4.aoi_r4 B1 ) ( read_w0_p1_b3.aoi_r4 B1 ) ( read_w0_p1_b2.aoi_r4 B1 ) ++ ( read_w0_p1_b1.aoi_r4 B1 ) ( read_w0_p1_b0.aoi_r4 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_w0_p1_b7.aoi_r6 A1 ) ( read_w0_p1_b6.aoi_r6 A1 ) ( read_w0_p1_b5.aoi_r6 A1 ) ( read_w0_p1_b4.aoi_r6 A1 ) ( read_w0_p1_b3.aoi_r6 A1 ) ( read_w0_p1_b2.aoi_r6 A1 ) ++ ( read_w0_p1_b1.aoi_r6 A1 ) ( read_w0_p1_b0.aoi_r6 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_w0_p1_b7.aoi_r6 B1 ) ( read_w0_p1_b6.aoi_r6 B1 ) ( read_w0_p1_b5.aoi_r6 B1 ) ( read_w0_p1_b4.aoi_r6 B1 ) ( read_w0_p1_b3.aoi_r6 B1 ) ( read_w0_p1_b2.aoi_r6 B1 ) ++ ( read_w0_p1_b1.aoi_r6 B1 ) ( read_w0_p1_b0.aoi_r6 B1 ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_2 ( read_w0_p0_b0.nand_r0_4 A ) ( read_w0_p0_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t0_4 ( read_w0_p0_b0.nor_r0_8 A ) ( read_w0_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t2_4 ( read_w0_p0_b0.aoi_r2 Y ) ( read_w0_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_6 ( read_w0_p0_b0.nand_r4_8 A ) ( read_w0_p0_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b0.t4_8 ( read_w0_p0_b0.nand_r4_8 Y ) ( read_w0_p0_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b0.t6_8 ( read_w0_p0_b0.aoi_r6 Y ) ( read_w0_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_2 ( read_w0_p0_b1.nand_r0_4 A ) ( read_w0_p0_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t0_4 ( read_w0_p0_b1.nor_r0_8 A ) ( read_w0_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t2_4 ( read_w0_p0_b1.aoi_r2 Y ) ( read_w0_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_6 ( read_w0_p0_b1.nand_r4_8 A ) ( read_w0_p0_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b1.t4_8 ( read_w0_p0_b1.nand_r4_8 Y ) ( read_w0_p0_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b1.t6_8 ( read_w0_p0_b1.aoi_r6 Y ) ( read_w0_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_2 ( read_w0_p0_b2.nand_r0_4 A ) ( read_w0_p0_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t0_4 ( read_w0_p0_b2.nor_r0_8 A ) ( read_w0_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t2_4 ( read_w0_p0_b2.aoi_r2 Y ) ( read_w0_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_6 ( read_w0_p0_b2.nand_r4_8 A ) ( read_w0_p0_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b2.t4_8 ( read_w0_p0_b2.nand_r4_8 Y ) ( read_w0_p0_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b2.t6_8 ( read_w0_p0_b2.aoi_r6 Y ) ( read_w0_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_2 ( read_w0_p0_b3.nand_r0_4 A ) ( read_w0_p0_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t0_4 ( read_w0_p0_b3.nor_r0_8 A ) ( read_w0_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t2_4 ( read_w0_p0_b3.aoi_r2 Y ) ( read_w0_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_6 ( read_w0_p0_b3.nand_r4_8 A ) ( read_w0_p0_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b3.t4_8 ( read_w0_p0_b3.nand_r4_8 Y ) ( read_w0_p0_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b3.t6_8 ( read_w0_p0_b3.aoi_r6 Y ) ( read_w0_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_2 ( read_w0_p0_b4.nand_r0_4 A ) ( read_w0_p0_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t0_4 ( read_w0_p0_b4.nor_r0_8 A ) ( read_w0_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t2_4 ( read_w0_p0_b4.aoi_r2 Y ) ( read_w0_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_6 ( read_w0_p0_b4.nand_r4_8 A ) ( read_w0_p0_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b4.t4_8 ( read_w0_p0_b4.nand_r4_8 Y ) ( read_w0_p0_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b4.t6_8 ( read_w0_p0_b4.aoi_r6 Y ) ( read_w0_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_2 ( read_w0_p0_b5.nand_r0_4 A ) ( read_w0_p0_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t0_4 ( read_w0_p0_b5.nor_r0_8 A ) ( read_w0_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t2_4 ( read_w0_p0_b5.aoi_r2 Y ) ( read_w0_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_6 ( read_w0_p0_b5.nand_r4_8 A ) ( read_w0_p0_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b5.t4_8 ( read_w0_p0_b5.nand_r4_8 Y ) ( read_w0_p0_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b5.t6_8 ( read_w0_p0_b5.aoi_r6 Y ) ( read_w0_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_2 ( read_w0_p0_b6.nand_r0_4 A ) ( read_w0_p0_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t0_4 ( read_w0_p0_b6.nor_r0_8 A ) ( read_w0_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t2_4 ( read_w0_p0_b6.aoi_r2 Y ) ( read_w0_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_6 ( read_w0_p0_b6.nand_r4_8 A ) ( read_w0_p0_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b6.t4_8 ( read_w0_p0_b6.nand_r4_8 Y ) ( read_w0_p0_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b6.t6_8 ( read_w0_p0_b6.aoi_r6 Y ) ( read_w0_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_2 ( read_w0_p0_b7.nand_r0_4 A ) ( read_w0_p0_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t0_4 ( read_w0_p0_b7.nor_r0_8 A ) ( read_w0_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t2_4 ( read_w0_p0_b7.aoi_r2 Y ) ( read_w0_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_6 ( read_w0_p0_b7.nand_r4_8 A ) ( read_w0_p0_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p0_b7.t4_8 ( read_w0_p0_b7.nand_r4_8 Y ) ( read_w0_p0_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p0_b7.t6_8 ( read_w0_p0_b7.aoi_r6 Y ) ( read_w0_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_2 ( read_w0_p1_b0.nand_r0_4 A ) ( read_w0_p1_b0.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t0_4 ( read_w0_p1_b0.nor_r0_8 A ) ( read_w0_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t2_4 ( read_w0_p1_b0.aoi_r2 Y ) ( read_w0_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_6 ( read_w0_p1_b0.nand_r4_8 A ) ( read_w0_p1_b0.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b0.t4_8 ( read_w0_p1_b0.nand_r4_8 Y ) ( read_w0_p1_b0.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b0.t6_8 ( read_w0_p1_b0.aoi_r6 Y ) ( read_w0_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_2 ( read_w0_p1_b1.nand_r0_4 A ) ( read_w0_p1_b1.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t0_4 ( read_w0_p1_b1.nor_r0_8 A ) ( read_w0_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t2_4 ( read_w0_p1_b1.aoi_r2 Y ) ( read_w0_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_6 ( read_w0_p1_b1.nand_r4_8 A ) ( read_w0_p1_b1.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b1.t4_8 ( read_w0_p1_b1.nand_r4_8 Y ) ( read_w0_p1_b1.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b1.t6_8 ( read_w0_p1_b1.aoi_r6 Y ) ( read_w0_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_2 ( read_w0_p1_b2.nand_r0_4 A ) ( read_w0_p1_b2.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t0_4 ( read_w0_p1_b2.nor_r0_8 A ) ( read_w0_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t2_4 ( read_w0_p1_b2.aoi_r2 Y ) ( read_w0_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_6 ( read_w0_p1_b2.nand_r4_8 A ) ( read_w0_p1_b2.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b2.t4_8 ( read_w0_p1_b2.nand_r4_8 Y ) ( read_w0_p1_b2.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b2.t6_8 ( read_w0_p1_b2.aoi_r6 Y ) ( read_w0_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_2 ( read_w0_p1_b3.nand_r0_4 A ) ( read_w0_p1_b3.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t0_4 ( read_w0_p1_b3.nor_r0_8 A ) ( read_w0_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t2_4 ( read_w0_p1_b3.aoi_r2 Y ) ( read_w0_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_6 ( read_w0_p1_b3.nand_r4_8 A ) ( read_w0_p1_b3.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b3.t4_8 ( read_w0_p1_b3.nand_r4_8 Y ) ( read_w0_p1_b3.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b3.t6_8 ( read_w0_p1_b3.aoi_r6 Y ) ( read_w0_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_2 ( read_w0_p1_b4.nand_r0_4 A ) ( read_w0_p1_b4.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t0_4 ( read_w0_p1_b4.nor_r0_8 A ) ( read_w0_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t2_4 ( read_w0_p1_b4.aoi_r2 Y ) ( read_w0_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_6 ( read_w0_p1_b4.nand_r4_8 A ) ( read_w0_p1_b4.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b4.t4_8 ( read_w0_p1_b4.nand_r4_8 Y ) ( read_w0_p1_b4.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b4.t6_8 ( read_w0_p1_b4.aoi_r6 Y ) ( read_w0_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_2 ( read_w0_p1_b5.nand_r0_4 A ) ( read_w0_p1_b5.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t0_4 ( read_w0_p1_b5.nor_r0_8 A ) ( read_w0_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t2_4 ( read_w0_p1_b5.aoi_r2 Y ) ( read_w0_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_6 ( read_w0_p1_b5.nand_r4_8 A ) ( read_w0_p1_b5.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b5.t4_8 ( read_w0_p1_b5.nand_r4_8 Y ) ( read_w0_p1_b5.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b5.t6_8 ( read_w0_p1_b5.aoi_r6 Y ) ( read_w0_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_2 ( read_w0_p1_b6.nand_r0_4 A ) ( read_w0_p1_b6.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t0_4 ( read_w0_p1_b6.nor_r0_8 A ) ( read_w0_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t2_4 ( read_w0_p1_b6.aoi_r2 Y ) ( read_w0_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_6 ( read_w0_p1_b6.nand_r4_8 A ) ( read_w0_p1_b6.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b6.t4_8 ( read_w0_p1_b6.nand_r4_8 Y ) ( read_w0_p1_b6.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b6.t6_8 ( read_w0_p1_b6.aoi_r6 Y ) ( read_w0_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_2 ( read_w0_p1_b7.nand_r0_4 A ) ( read_w0_p1_b7.aoi_r0 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t0_4 ( read_w0_p1_b7.nor_r0_8 A ) ( read_w0_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t2_4 ( read_w0_p1_b7.aoi_r2 Y ) ( read_w0_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_6 ( read_w0_p1_b7.nand_r4_8 A ) ( read_w0_p1_b7.aoi_r4 Y ) + USE SIGNAL ; ++ - read_w0_p1_b7.t4_8 ( read_w0_p1_b7.nand_r4_8 Y ) ( read_w0_p1_b7.nor_r0_8 B ) + USE SIGNAL ; ++ - read_w0_p1_b7.t6_8 ( read_w0_p1_b7.aoi_r6 Y ) ( read_w0_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_0_0.bit0.storage ( read_w0_p1_b0.aoi_r0 A2 ) ( read_w0_p0_b0.aoi_r0 A2 ) ( storage_0_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit1.storage ( read_w0_p1_b1.aoi_r0 A2 ) ( read_w0_p0_b1.aoi_r0 A2 ) ( storage_0_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit2.storage ( read_w0_p1_b2.aoi_r0 A2 ) ( read_w0_p0_b2.aoi_r0 A2 ) ( storage_0_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit3.storage ( read_w0_p1_b3.aoi_r0 A2 ) ( read_w0_p0_b3.aoi_r0 A2 ) ( storage_0_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit4.storage ( read_w0_p1_b4.aoi_r0 A2 ) ( read_w0_p0_b4.aoi_r0 A2 ) ( storage_0_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit5.storage ( read_w0_p1_b5.aoi_r0 A2 ) ( read_w0_p0_b5.aoi_r0 A2 ) ( storage_0_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit6.storage ( read_w0_p1_b6.aoi_r0 A2 ) ( read_w0_p0_b6.aoi_r0 A2 ) ( storage_0_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.bit7.storage ( read_w0_p1_b7.aoi_r0 A2 ) ( read_w0_p0_b7.aoi_r0 A2 ) ( storage_0_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_0_0.gclock ( storage_0_0_0.cg GCLK ) ( storage_0_0_0.bit7.bit CLK ) ( storage_0_0_0.bit6.bit CLK ) ( storage_0_0_0.bit5.bit CLK ) ( storage_0_0_0.bit4.bit CLK ) ( storage_0_0_0.bit3.bit CLK ) ( storage_0_0_0.bit2.bit CLK ) ++ ( storage_0_0_0.bit1.bit CLK ) ( storage_0_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_0_0.we ( storage_0_0_0.gcand Y ) ( storage_0_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r0 B2 ) ( read_w0_p0_b0.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r0 B2 ) ( read_w0_p0_b1.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r0 B2 ) ( read_w0_p0_b2.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r0 B2 ) ( read_w0_p0_b3.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r0 B2 ) ( read_w0_p0_b4.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r0 B2 ) ( read_w0_p0_b5.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r0 B2 ) ( read_w0_p0_b6.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r0 B2 ) ( read_w0_p0_b7.aoi_r0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_w0_p1_b0.aoi_r2 A2 ) ( read_w0_p0_b0.aoi_r2 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_w0_p1_b1.aoi_r2 A2 ) ( read_w0_p0_b1.aoi_r2 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_w0_p1_b2.aoi_r2 A2 ) ( read_w0_p0_b2.aoi_r2 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_w0_p1_b3.aoi_r2 A2 ) ( read_w0_p0_b3.aoi_r2 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_w0_p1_b4.aoi_r2 A2 ) ( read_w0_p0_b4.aoi_r2 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_w0_p1_b5.aoi_r2 A2 ) ( read_w0_p0_b5.aoi_r2 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_w0_p1_b6.aoi_r2 A2 ) ( read_w0_p0_b6.aoi_r2 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_w0_p1_b7.aoi_r2 A2 ) ( read_w0_p0_b7.aoi_r2 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r2 B2 ) ( read_w0_p0_b0.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r2 B2 ) ( read_w0_p0_b1.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r2 B2 ) ( read_w0_p0_b2.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r2 B2 ) ( read_w0_p0_b3.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r2 B2 ) ( read_w0_p0_b4.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r2 B2 ) ( read_w0_p0_b5.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r2 B2 ) ( read_w0_p0_b6.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r2 B2 ) ( read_w0_p0_b7.aoi_r2 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_4_0_0.bit0.storage ( read_w0_p1_b0.aoi_r4 A2 ) ( read_w0_p0_b0.aoi_r4 A2 ) ( storage_4_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit1.storage ( read_w0_p1_b1.aoi_r4 A2 ) ( read_w0_p0_b1.aoi_r4 A2 ) ( storage_4_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit2.storage ( read_w0_p1_b2.aoi_r4 A2 ) ( read_w0_p0_b2.aoi_r4 A2 ) ( storage_4_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit3.storage ( read_w0_p1_b3.aoi_r4 A2 ) ( read_w0_p0_b3.aoi_r4 A2 ) ( storage_4_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit4.storage ( read_w0_p1_b4.aoi_r4 A2 ) ( read_w0_p0_b4.aoi_r4 A2 ) ( storage_4_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit5.storage ( read_w0_p1_b5.aoi_r4 A2 ) ( read_w0_p0_b5.aoi_r4 A2 ) ( storage_4_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit6.storage ( read_w0_p1_b6.aoi_r4 A2 ) ( read_w0_p0_b6.aoi_r4 A2 ) ( storage_4_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.bit7.storage ( read_w0_p1_b7.aoi_r4 A2 ) ( read_w0_p0_b7.aoi_r4 A2 ) ( storage_4_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_4_0_0.gclock ( storage_4_0_0.cg GCLK ) ( storage_4_0_0.bit7.bit CLK ) ( storage_4_0_0.bit6.bit CLK ) ( storage_4_0_0.bit5.bit CLK ) ( storage_4_0_0.bit4.bit CLK ) ( storage_4_0_0.bit3.bit CLK ) ( storage_4_0_0.bit2.bit CLK ) ++ ( storage_4_0_0.bit1.bit CLK ) ( storage_4_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_4_0_0.we ( storage_4_0_0.gcand Y ) ( storage_4_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_5_0_0.bit0.storage ( storage_5_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r4 B2 ) ( read_w0_p0_b0.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit1.storage ( storage_5_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r4 B2 ) ( read_w0_p0_b1.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit2.storage ( storage_5_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r4 B2 ) ( read_w0_p0_b2.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit3.storage ( storage_5_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r4 B2 ) ( read_w0_p0_b3.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit4.storage ( storage_5_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r4 B2 ) ( read_w0_p0_b4.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit5.storage ( storage_5_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r4 B2 ) ( read_w0_p0_b5.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit6.storage ( storage_5_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r4 B2 ) ( read_w0_p0_b6.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.bit7.storage ( storage_5_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r4 B2 ) ( read_w0_p0_b7.aoi_r4 B2 ) + USE SIGNAL ; ++ - storage_5_0_0.gclock ( storage_5_0_0.cg GCLK ) ( storage_5_0_0.bit7.bit CLK ) ( storage_5_0_0.bit6.bit CLK ) ( storage_5_0_0.bit5.bit CLK ) ( storage_5_0_0.bit4.bit CLK ) ( storage_5_0_0.bit3.bit CLK ) ( storage_5_0_0.bit2.bit CLK ) ++ ( storage_5_0_0.bit1.bit CLK ) ( storage_5_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_5_0_0.we ( storage_5_0_0.gcand Y ) ( storage_5_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_6_0_0.bit0.storage ( read_w0_p1_b0.aoi_r6 A2 ) ( read_w0_p0_b0.aoi_r6 A2 ) ( storage_6_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit1.storage ( read_w0_p1_b1.aoi_r6 A2 ) ( read_w0_p0_b1.aoi_r6 A2 ) ( storage_6_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit2.storage ( read_w0_p1_b2.aoi_r6 A2 ) ( read_w0_p0_b2.aoi_r6 A2 ) ( storage_6_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit3.storage ( read_w0_p1_b3.aoi_r6 A2 ) ( read_w0_p0_b3.aoi_r6 A2 ) ( storage_6_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit4.storage ( read_w0_p1_b4.aoi_r6 A2 ) ( read_w0_p0_b4.aoi_r6 A2 ) ( storage_6_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit5.storage ( read_w0_p1_b5.aoi_r6 A2 ) ( read_w0_p0_b5.aoi_r6 A2 ) ( storage_6_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit6.storage ( read_w0_p1_b6.aoi_r6 A2 ) ( read_w0_p0_b6.aoi_r6 A2 ) ( storage_6_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.bit7.storage ( read_w0_p1_b7.aoi_r6 A2 ) ( read_w0_p0_b7.aoi_r6 A2 ) ( storage_6_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_6_0_0.gclock ( storage_6_0_0.cg GCLK ) ( storage_6_0_0.bit7.bit CLK ) ( storage_6_0_0.bit6.bit CLK ) ( storage_6_0_0.bit5.bit CLK ) ( storage_6_0_0.bit4.bit CLK ) ( storage_6_0_0.bit3.bit CLK ) ( storage_6_0_0.bit2.bit CLK ) ++ ( storage_6_0_0.bit1.bit CLK ) ( storage_6_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_6_0_0.we ( storage_6_0_0.gcand Y ) ( storage_6_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_7_0_0.bit0.storage ( storage_7_0_0.bit0.bit QN ) ( read_w0_p1_b0.aoi_r6 B2 ) ( read_w0_p0_b0.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit1.storage ( storage_7_0_0.bit1.bit QN ) ( read_w0_p1_b1.aoi_r6 B2 ) ( read_w0_p0_b1.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit2.storage ( storage_7_0_0.bit2.bit QN ) ( read_w0_p1_b2.aoi_r6 B2 ) ( read_w0_p0_b2.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit3.storage ( storage_7_0_0.bit3.bit QN ) ( read_w0_p1_b3.aoi_r6 B2 ) ( read_w0_p0_b3.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit4.storage ( storage_7_0_0.bit4.bit QN ) ( read_w0_p1_b4.aoi_r6 B2 ) ( read_w0_p0_b4.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit5.storage ( storage_7_0_0.bit5.bit QN ) ( read_w0_p1_b5.aoi_r6 B2 ) ( read_w0_p0_b5.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit6.storage ( storage_7_0_0.bit6.bit QN ) ( read_w0_p1_b6.aoi_r6 B2 ) ( read_w0_p0_b6.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.bit7.storage ( storage_7_0_0.bit7.bit QN ) ( read_w0_p1_b7.aoi_r6 B2 ) ( read_w0_p0_b7.aoi_r6 B2 ) + USE SIGNAL ; ++ - storage_7_0_0.gclock ( storage_7_0_0.cg GCLK ) ( storage_7_0_0.bit7.bit CLK ) ( storage_7_0_0.bit6.bit CLK ) ( storage_7_0_0.bit5.bit CLK ) ( storage_7_0_0.bit4.bit CLK ) ( storage_7_0_0.bit3.bit CLK ) ( storage_7_0_0.bit2.bit CLK ) ++ ( storage_7_0_0.bit1.bit CLK ) ( storage_7_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_7_0_0.we ( storage_7_0_0.gcand Y ) ( storage_7_0_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) ( storage_0_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_4_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_5_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_6_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_7_0_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_7_0_0.gcand B ) ( storage_6_0_0.gcand B ) ( storage_5_0_0.gcand B ) ( storage_4_0_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_0_0.gcand B ) ++ ( storage_1_0_0.gcand B ) ( storage_0_0_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_service_asap7.tcl b/src/ram/test/make_8x8_2r1w_service_asap7.tcl +new file mode 100644 +index 0000000000..90012ecfee +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_service_asap7.tcl +@@ -0,0 +1,33 @@ ++# generate_ram on asap7 with an empty column of 10 sites after every 4 ++# storage columns (-service_columns), room for a parent's buffers inside ++# the array. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_service_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -service_columns {4 10} \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_service_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_service_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_service_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_service_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_service_asap7_behavioral.vok +new file mode 100644 +index 0000000000..a5a0666525 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_service_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i]) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index 9ca6d25ce3..0dc0ecc2c4 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -14,6 +14,7 @@ record_tests { + make_8x8_rb_latency_asap7 + make_8x8_2r1w_mux_asap7 + make_8x8_2r2w_or_asap7 ++ make_8x8_2r1w_service_asap7 + make_8x8_2r1w_unplaced_asap7 + make_8x8_latch_sky130 + } diff --git a/patches/0026-openroad-ram-bank-column-layout.patch b/patches/0026-openroad-ram-bank-column-layout.patch new file mode 100644 index 000000000..665bf45f5 --- /dev/null +++ b/patches/0026-openroad-ram-bank-column-layout.patch @@ -0,0 +1,1035 @@ +From: =?UTF-8?q?=C3=98yvind=20Harboe?= +Subject: [PATCH] ram: generate_ram -bank_column_layout, a word's bits contiguous + +With banks a row holds -bank_columns words, laid out as the column mux +lays out its words: bit by bit, interleaved. Each word is decoded whole, +so nothing reads the row through a mux, and the interleave only costs: +a word's selects and write enables run the whole row to reach its bits. +-bank_column_layout contiguous puts each word's bits side by side with +its select column after them; the per-bit read trees cross the row +instead. XiangShan's RobEntryFile (352 words of 21 bits, 16 read and 8 +write ports, 4 words a row) had rows 278 um wide: dissolved into a +parent, the resizer found 6,483 slew violations on those nets and put +6,043 buffers inside the full array, which detailed placement could not +legalize. Default: interleaved, as before. + +The sixteenth of the generate_regfile features carried onto +generate_ram; see OpenROAD #11669. Not upstreamed. + +--- +diff --git a/src/ram/README.md b/src/ram/README.md +index c0d4089d01..370260a91a 100644 +--- a/src/ram/README.md ++++ b/src/ram/README.md +@@ -54,6 +54,7 @@ generate_ram [-mask_size bits] + [-write_style clock_gate|mux] + [-write_priority last|or] + [-service_columns {every sites}] ++ [-bank_column_layout interleaved|contiguous] + [-cells {role master ...}] + [-name name] + [-decoder row|word] +@@ -91,6 +92,7 @@ generate_ram [-mask_size bits] + | `-write_style` | How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock. Not with `-use_latch`. Default: `clock_gate`. | + | `-write_priority` | Where two write ports write the same word in one cycle: `last`, the last port's data; or `or`, the OR of every writing port's data, as RTL that merges its writes with an OR describes it (firtool's register files). `or` drops a word's priority logic, an inverter and an AND2 per port but the last. Default: `last`. | + | `-service_columns {every sites}` | An empty column `sites` sites wide after every `every` storage columns: room inside the array for the buffers a parent flow inserts on the long nets that cross it, where the array is otherwise full. Default: none. | ++| `-bank_column_layout interleaved\|contiguous` | With banks, how a row's words share its columns: `interleaved`, bit by bit as the column mux lays them out; or `contiguous`, each word's bits side by side with its select column after them. Contiguous keeps a word's selects and write enables as short as its own bits, where interleaved runs them the whole row; the read trees then cross the row instead. Default: `interleaved`. | + | `-periphery`, `-pin_layer` | `generate_ram_netlist` only. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. Default: `placed`. | + | `-cells` | The cell for a role (`inv`, `and2`, `buffer`, `clock_gate`, `aoi22`, `ao22`, `or2`, `nand2`, `nor2`, `tie`, `addr_flop`), instead of the smallest the libraries have of its function. An AOI22 or AO22 given is checked by its truth table. Default: the smallest of each. | + | `-name` | The block's and the behavioral model's name. Default: `RAMx`. | +diff --git a/src/ram/include/ram/ram.h b/src/ram/include/ram/ram.h +index cecaf6716f..56836a434e 100644 +--- a/src/ram/include/ram/ram.h ++++ b/src/ram/include/ram/ram.h +@@ -128,7 +128,8 @@ class RamGen + int bit_folds = 1, + const std::string& wrapper_verilog = "", + int service_every = 0, +- int service_sites = 0); ++ int service_sites = 0, ++ const std::string& bank_column_layout = "interleaved"); + + void ramPdngen(const char* power_net_name, + const char* ground_net_name, +@@ -416,6 +417,24 @@ class RamGen + { + return bit_folds_ > 1 ? 0 : slice * slice_width_; + } ++ // -bank_column_layout: a row's words interleaved bit by bit, as the ++ // column mux lays them out (bit b of every word, then bit b+1), or ++ // contiguous, each word's bits side by side and its select column ++ // after them, so a word's selects and write enables span its own bits ++ // and not the row ++ bool words_contiguous_{false}; ++ int bitColumn(int slice, int bit, int word, int mask_size) const ++ { ++ return sliceOffset(slice) ++ + (words_contiguous_ ? word * (mask_size + 1) + bit ++ : bit * words_per_row_ + word); ++ } ++ int selColumn(int slice, int word, int mask_size) const ++ { ++ return sliceOffset(slice) ++ + (words_contiguous_ ? word * (mask_size + 1) + mask_size ++ : mask_size * words_per_row_ + word); ++ } + std::string pin_layer_; + bool marking_periphery_{false}; + Cell* periphery_cell_{nullptr}; +diff --git a/src/ram/src/ram.cpp b/src/ram/src/ram.cpp +index 0bb65688bb..2cf7add964 100644 +--- a/src/ram/src/ram.cpp ++++ b/src/ram/src/ram.cpp +@@ -350,12 +350,9 @@ void RamGen::makeSlice(const int slice_idx, + } + } + ram_grid_.addCell(std::move(cell), +- sliceOffset(slice_idx) +- + local_bit * column_mux_ratio + word_idx); ++ bitColumn(slice_idx, local_bit, word_idx, mask_size)); + } +- ram_grid_.addCell(nullptr, +- sliceOffset(slice_idx) +- + mask_size * column_mux_ratio + word_idx); ++ ram_grid_.addCell(nullptr, selColumn(slice_idx, word_idx, mask_size)); + return; + } + +@@ -515,8 +512,7 @@ void RamGen::makeSlice(const int slice_idx, + if (start_bit_idx + local_bit >= word_bits_) { + // a short fold's pad: its column empty in this row + ram_grid_.addCell(nullptr, +- sliceOffset(slice_idx) +- + local_bit * column_mux_ratio + word_idx); ++ bitColumn(slice_idx, local_bit, word_idx, mask_size)); + continue; + } + auto name = fmt::format("{}.bit{}", prefix, start_bit_idx + local_bit); +@@ -634,8 +630,7 @@ void RamGen::makeSlice(const int slice_idx, + } + } + +- int bit_col = sliceOffset(slice_idx) +- + local_bit * column_mux_ratio + word_idx; ++ int bit_col = bitColumn(slice_idx, local_bit, word_idx, mask_size); + ram_grid_.addCell(std::move(bit_cell), bit_col); + } + +@@ -693,8 +688,7 @@ void RamGen::makeSlice(const int slice_idx, + } + } + +- int sel_col = sliceOffset(slice_idx) +- + mask_size * column_mux_ratio + word_idx; ++ int sel_col = selColumn(slice_idx, word_idx, mask_size); + // a fold sharing its word's logic has an empty select cell + ram_grid_.addCell(shared ? nullptr : std::move(sel_cell), sel_col); + } +@@ -1960,7 +1954,8 @@ void RamGen::generate(const int mask_size, + const int bit_folds, + const std::string& wrapper_verilog, + const int service_every, +- const int service_sites) ++ const int service_sites, ++ const std::string& bank_column_layout) + { + // Banks: every port decodes every word's whole address, and a row holds + // bank_columns words, laid out as the column mux lays out its words; +@@ -2031,6 +2026,14 @@ void RamGen::generate(const int mask_size, + // the words in a row: the column mux's, or the banks side by side + const int column_mux_ratio = banked_ ? bank_columns_ : column_mux_ratio_arg; + words_per_row_ = column_mux_ratio; ++ words_contiguous_ = bank_column_layout == "contiguous"; ++ if (words_contiguous_ && !banked_) { ++ logger_->error(RAM, ++ 90, ++ "-bank_column_layout contiguous needs -banks, -bank_columns " ++ "or -decoder word: the column mux reads a row's words " ++ "interleaved."); ++ } + bit_folds_ = std::max(bit_folds, 1); + slice_width_ = mask_size * column_mux_ratio + column_mux_ratio; + // the word's own bits; with -bit_folds the last fold may be short, its +@@ -2869,7 +2872,7 @@ void RamGen::generate(const int mask_size, + for (int slice = 0; slice < slices_per_word; ++slice) { + for (int bit = 0; bit < mask_size; ++bit) { + int bit_idx = bit + slice * mask_size; +- int buf_col = sliceOffset(slice) + bit * column_mux_ratio; ++ int buf_col = bitColumn(slice, bit, 0, mask_size); + auto& buffer_grid_cell + = buffer_cells[{buf_col, bit_folds_ > 1 ? slice : 0}]; + if (bit_idx >= word_bits_) { +diff --git a/src/ram/src/ram.i b/src/ram/src/ram.i +index b70e571e2f..969aef4d08 100644 +--- a/src/ram/src/ram.i ++++ b/src/ram/src/ram.i +@@ -60,7 +60,8 @@ generate_ram_netlist_cmd(int mask_size, + const int bit_folds, + const char* wrapper_verilog, + const int service_every, +- const int service_sites) ++ const int service_sites, ++ const char* bank_column_layout) + { + RamGen* ram_gen = ord::getRamGen(); + odb::dbDatabase* db = ord::getDb(); +@@ -116,7 +117,7 @@ generate_ram_netlist_cmd(int mask_size, + reset_value, banks, bank_columns, bank_order, rb_ports, + read_latency, write_style, write_priority, periphery, pin_layer, cells, + name, decoder, bit_folds, wrapper_verilog, +- service_every, service_sites); ++ service_every, service_sites, bank_column_layout); + } + + void ram_pdngen(const char* power_net_name, const char* ground_net_name, +diff --git a/src/ram/src/ram.tcl b/src/ram/src/ram.tcl +index df0de59aae..bf0ba910ba 100644 +--- a/src/ram/src/ram.tcl ++++ b/src/ram/src/ram.tcl +@@ -38,6 +38,7 @@ sta::define_cmd_args "generate_ram_netlist" {[-mask_size bits] + [-decoder row|word] + [-bit_folds count] + [-service_columns {every sites}] ++ [-bank_column_layout interleaved|contiguous] + [-inv_cell name] + [-rw_ports count] + [-r_ports count] +@@ -52,7 +53,8 @@ proc generate_ram_netlist { args } { + -rw_ports -r_ports -w_ports -use_latch -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority +- -periphery -pin_layer -cells -name -decoder -bit_folds -wrapper_verilog -service_columns } flags {} ++ -periphery -pin_layer -cells -name -decoder -bit_folds -wrapper_verilog -service_columns ++ -bank_column_layout } flags {} + + set column_mux_ratio 1 + if { [info exists keys(-column_mux_ratio)] } { +@@ -245,6 +247,16 @@ proc generate_ram_netlist { args } { + lassign $keys(-service_columns) service_every service_sites + } + ++ # A row's words interleaved bit by bit (the column mux's order) or each ++ # word's bits side by side. ++ set bank_column_layout interleaved ++ if { [info exists keys(-bank_column_layout)] } { ++ set bank_column_layout $keys(-bank_column_layout) ++ if { $bank_column_layout ni {interleaved contiguous} } { ++ utl::error RAM 91 "-bank_column_layout is interleaved or contiguous, not $bank_column_layout." ++ } ++ } ++ + set bit_folds 1 + if { [info exists keys(-bit_folds)] } { + set bit_folds $keys(-bit_folds) +@@ -300,7 +312,8 @@ proc generate_ram_netlist { args } { + $column_mux_ratio $use_latch $storage_cell $tristate_cell $inv_cell $tapcell $max_tap_dist \ + $read_style $zero_word $reset_value $banks $bank_columns $bank_order \ + $rb_ports $read_latency $write_style $write_priority $periphery $pin_layer $cells $name \ +- $decoder $bit_folds $wrapper_verilog $service_every $service_sites ++ $decoder $bit_folds $wrapper_verilog $service_every $service_sites \ ++ $bank_column_layout + } + + sta::define_cmd_args "generate_ram" {[-mask_size bits] +@@ -336,7 +349,8 @@ proc generate_ram { args } { + -hor_layer -filler_cells -tapcell -max_tap_dist + -write_behavioral_verilog -read_style -zero_word -reset_value + -banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority +- -cells -name -decoder -bit_folds -service_columns } flags {} ++ -cells -name -decoder -bit_folds -service_columns ++ -bank_column_layout } flags {} + + sta::check_argc_eq0 "generate_ram" $args + +@@ -386,7 +400,8 @@ proc generate_ram { args } { + } + + foreach key {-banks -bank_columns -bank_order -rb_ports -read_latency -write_style -write_priority +- -cells -name -decoder -bit_folds -service_columns} { ++ -cells -name -decoder -bit_folds -service_columns ++ -bank_column_layout} { + if { [info exists keys($key)] } { + lappend ram_netlist_args $key $keys($key) + } +diff --git a/src/ram/test/BUILD b/src/ram/test/BUILD +index 2ac84e6040..fca2571f0c 100644 +--- a/src/ram/test/BUILD ++++ b/src/ram/test/BUILD +@@ -17,6 +17,7 @@ PASSFAIL_TESTS = [ + "make_8x8_2r1w_mux_asap7", + "make_8x8_2r2w_or_asap7", + "make_8x8_2r1w_service_asap7", ++ "make_8x8_2r1w_contiguous_asap7", + "make_8x8_rb_latency_asap7", + "make_8x8_rb_asap7", + "make_8x8_2r1w_banks_asap7", +@@ -92,6 +93,11 @@ filegroup( + "//test:asap7_nldm_data", + "make_8x8_2r1w_mux_asap7_behavioral.vok", + ], ++ "make_8x8_2r1w_contiguous_asap7": [ ++ "//test:asap7_data", ++ "//test:asap7_nldm_data", ++ "make_8x8_2r1w_contiguous_asap7_behavioral.vok", ++ ], + "make_8x8_2r1w_service_asap7": [ + "//test:asap7_data", + "//test:asap7_nldm_data", +diff --git a/src/ram/test/make_8x8_2r1w_contiguous_asap7.defok b/src/ram/test/make_8x8_2r1w_contiguous_asap7.defok +new file mode 100644 +index 0000000000..3556afb25e +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_contiguous_asap7.defok +@@ -0,0 +1,649 @@ ++VERSION 5.8 ; ++DIVIDERCHAR "/" ; ++BUSBITCHARS "[]" ; ++DESIGN RAM8x8 ; ++UNITS DISTANCE MICRONS 100 ; ++DIEAREA ( 0 0 ) ( 3591 135 ) ; ++ROW RAM_ROW0 asap7sc7p5t 0 0 N DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW1 asap7sc7p5t 0 27 FS DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW2 asap7sc7p5t 0 54 N DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW3 asap7sc7p5t 0 81 FS DO 665 BY 1 STEP 5 0 ; ++ROW RAM_ROW4 asap7sc7p5t 0 108 N DO 665 BY 1 STEP 5 0 ; ++COMPONENTS 271 ; ++ - buffer.in[0] HB1xp67_ASAP7_75t_R + PLACED ( 0 108 ) N ; ++ - buffer.in[1] HB1xp67_ASAP7_75t_R + PLACED ( 172 108 ) N ; ++ - buffer.in[2] HB1xp67_ASAP7_75t_R + PLACED ( 345 108 ) N ; ++ - buffer.in[3] HB1xp67_ASAP7_75t_R + PLACED ( 518 108 ) N ; ++ - buffer.in[4] HB1xp67_ASAP7_75t_R + PLACED ( 691 108 ) N ; ++ - buffer.in[5] HB1xp67_ASAP7_75t_R + PLACED ( 864 108 ) N ; ++ - buffer.in[6] HB1xp67_ASAP7_75t_R + PLACED ( 1036 108 ) N ; ++ - buffer.in[7] HB1xp67_ASAP7_75t_R + PLACED ( 1209 108 ) N ; ++ - decoder_p0.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3067 0 ) N ; ++ - decoder_p0.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3132 0 ) N ; ++ - decoder_p0.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3067 27 ) FS ; ++ - decoder_p0.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3132 27 ) FS ; ++ - decoder_p0.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3067 54 ) N ; ++ - decoder_p0.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3132 54 ) N ; ++ - decoder_p0.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3067 81 ) FS ; ++ - decoder_p0.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3132 81 ) FS ; ++ - decoder_p0.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3099 0 ) N ; ++ - decoder_p0.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3164 0 ) N ; ++ - decoder_p0.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3099 27 ) FS ; ++ - decoder_p0.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3164 27 ) FS ; ++ - decoder_p0.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3099 54 ) N ; ++ - decoder_p0.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3164 54 ) N ; ++ - decoder_p0.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3099 81 ) FS ; ++ - decoder_p0.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3164 81 ) FS ; ++ - decoder_p0.inv_p0_a0 INVx1_ASAP7_75t_R + PLACED ( 3542 54 ) N ; ++ - decoder_p0.inv_p0_a1 INVx1_ASAP7_75t_R + PLACED ( 3542 27 ) FS ; ++ - decoder_p0.inv_p0_a2 INVx1_ASAP7_75t_R + PLACED ( 3542 0 ) N ; ++ - decoder_p1.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3240 0 ) N ; ++ - decoder_p1.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3304 0 ) N ; ++ - decoder_p1.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3240 27 ) FS ; ++ - decoder_p1.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3304 27 ) FS ; ++ - decoder_p1.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3240 54 ) N ; ++ - decoder_p1.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3304 54 ) N ; ++ - decoder_p1.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3240 81 ) FS ; ++ - decoder_p1.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3304 81 ) FS ; ++ - decoder_p1.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3272 0 ) N ; ++ - decoder_p1.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3337 0 ) N ; ++ - decoder_p1.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3272 27 ) FS ; ++ - decoder_p1.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3337 27 ) FS ; ++ - decoder_p1.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3272 54 ) N ; ++ - decoder_p1.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3337 54 ) N ; ++ - decoder_p1.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3272 81 ) FS ; ++ - decoder_p1.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3337 81 ) FS ; ++ - decoder_p1.inv_p1_a0 INVx1_ASAP7_75t_R + PLACED ( 3558 54 ) N ; ++ - decoder_p1.inv_p1_a1 INVx1_ASAP7_75t_R + PLACED ( 3558 27 ) FS ; ++ - decoder_p1.inv_p1_a2 INVx1_ASAP7_75t_R + PLACED ( 3558 0 ) N ; ++ - decoder_p2.and0_word0 AND2x2_ASAP7_75t_R + PLACED ( 3412 0 ) N ; ++ - decoder_p2.and0_word1 AND2x2_ASAP7_75t_R + PLACED ( 3477 0 ) N ; ++ - decoder_p2.and0_word2 AND2x2_ASAP7_75t_R + PLACED ( 3412 27 ) FS ; ++ - decoder_p2.and0_word3 AND2x2_ASAP7_75t_R + PLACED ( 3477 27 ) FS ; ++ - decoder_p2.and0_word4 AND2x2_ASAP7_75t_R + PLACED ( 3412 54 ) N ; ++ - decoder_p2.and0_word5 AND2x2_ASAP7_75t_R + PLACED ( 3477 54 ) N ; ++ - decoder_p2.and0_word6 AND2x2_ASAP7_75t_R + PLACED ( 3412 81 ) FS ; ++ - decoder_p2.and0_word7 AND2x2_ASAP7_75t_R + PLACED ( 3477 81 ) FS ; ++ - decoder_p2.and1_word0 AND2x2_ASAP7_75t_R + PLACED ( 3445 0 ) N ; ++ - decoder_p2.and1_word1 AND2x2_ASAP7_75t_R + PLACED ( 3510 0 ) N ; ++ - decoder_p2.and1_word2 AND2x2_ASAP7_75t_R + PLACED ( 3445 27 ) FS ; ++ - decoder_p2.and1_word3 AND2x2_ASAP7_75t_R + PLACED ( 3510 27 ) FS ; ++ - decoder_p2.and1_word4 AND2x2_ASAP7_75t_R + PLACED ( 3445 54 ) N ; ++ - decoder_p2.and1_word5 AND2x2_ASAP7_75t_R + PLACED ( 3510 54 ) N ; ++ - decoder_p2.and1_word6 AND2x2_ASAP7_75t_R + PLACED ( 3445 81 ) FS ; ++ - decoder_p2.and1_word7 AND2x2_ASAP7_75t_R + PLACED ( 3510 81 ) FS ; ++ - decoder_p2.inv_p2_a0 INVx1_ASAP7_75t_R + PLACED ( 3574 54 ) N ; ++ - decoder_p2.inv_p2_a1 INVx1_ASAP7_75t_R + PLACED ( 3574 27 ) FS ; ++ - decoder_p2.inv_p2_a2 INVx1_ASAP7_75t_R + PLACED ( 3574 0 ) N ; ++ - read_p0_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 0 0 ) N ; ++ - read_p0_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1620 0 ) N ; ++ - read_p0_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 108 54 ) N ; ++ - read_p0_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1620 54 ) N ; ++ - read_p0_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 108 27 ) FS ; ++ - read_p0_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1620 27 ) FS ; ++ - read_p0_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 108 81 ) FS ; ++ - read_p0_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 172 0 ) N ; ++ - read_p0_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1792 0 ) N ; ++ - read_p0_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 280 54 ) N ; ++ - read_p0_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1792 54 ) N ; ++ - read_p0_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 280 27 ) FS ; ++ - read_p0_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1792 27 ) FS ; ++ - read_p0_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 280 81 ) FS ; ++ - read_p0_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 345 0 ) N ; ++ - read_p0_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1965 0 ) N ; ++ - read_p0_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 453 54 ) N ; ++ - read_p0_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1965 54 ) N ; ++ - read_p0_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 453 27 ) FS ; ++ - read_p0_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1965 27 ) FS ; ++ - read_p0_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 453 81 ) FS ; ++ - read_p0_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 518 0 ) N ; ++ - read_p0_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2138 0 ) N ; ++ - read_p0_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 626 54 ) N ; ++ - read_p0_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2138 54 ) N ; ++ - read_p0_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 626 27 ) FS ; ++ - read_p0_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2138 27 ) FS ; ++ - read_p0_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 626 81 ) FS ; ++ - read_p0_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 691 0 ) N ; ++ - read_p0_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2311 0 ) N ; ++ - read_p0_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 799 54 ) N ; ++ - read_p0_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2311 54 ) N ; ++ - read_p0_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 799 27 ) FS ; ++ - read_p0_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2311 27 ) FS ; ++ - read_p0_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 799 81 ) FS ; ++ - read_p0_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 864 0 ) N ; ++ - read_p0_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2484 0 ) N ; ++ - read_p0_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 972 54 ) N ; ++ - read_p0_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2484 54 ) N ; ++ - read_p0_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 972 27 ) FS ; ++ - read_p0_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2484 27 ) FS ; ++ - read_p0_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 972 81 ) FS ; ++ - read_p0_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1036 0 ) N ; ++ - read_p0_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2656 0 ) N ; ++ - read_p0_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1144 54 ) N ; ++ - read_p0_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2656 54 ) N ; ++ - read_p0_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1144 27 ) FS ; ++ - read_p0_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2656 27 ) FS ; ++ - read_p0_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1144 81 ) FS ; ++ - read_p0_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1209 0 ) N ; ++ - read_p0_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2829 0 ) N ; ++ - read_p0_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1317 54 ) N ; ++ - read_p0_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2829 54 ) N ; ++ - read_p0_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1317 27 ) FS ; ++ - read_p0_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2829 27 ) FS ; ++ - read_p0_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1317 81 ) FS ; ++ - read_p1_b0.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 32 0 ) N ; ++ - read_p1_b0.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1652 0 ) N ; ++ - read_p1_b0.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 140 54 ) N ; ++ - read_p1_b0.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1652 54 ) N ; ++ - read_p1_b0.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 129 27 ) FS ; ++ - read_p1_b0.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1641 27 ) FS ; ++ - read_p1_b0.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 129 81 ) FS ; ++ - read_p1_b1.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 205 0 ) N ; ++ - read_p1_b1.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1825 0 ) N ; ++ - read_p1_b1.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 313 54 ) N ; ++ - read_p1_b1.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1825 54 ) N ; ++ - read_p1_b1.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 302 27 ) FS ; ++ - read_p1_b1.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1814 27 ) FS ; ++ - read_p1_b1.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 302 81 ) FS ; ++ - read_p1_b2.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 378 0 ) N ; ++ - read_p1_b2.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1998 0 ) N ; ++ - read_p1_b2.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 486 54 ) N ; ++ - read_p1_b2.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 1998 54 ) N ; ++ - read_p1_b2.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 475 27 ) FS ; ++ - read_p1_b2.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 1987 27 ) FS ; ++ - read_p1_b2.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 475 81 ) FS ; ++ - read_p1_b3.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 550 0 ) N ; ++ - read_p1_b3.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2170 0 ) N ; ++ - read_p1_b3.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 658 54 ) N ; ++ - read_p1_b3.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2170 54 ) N ; ++ - read_p1_b3.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 648 27 ) FS ; ++ - read_p1_b3.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2160 27 ) FS ; ++ - read_p1_b3.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 648 81 ) FS ; ++ - read_p1_b4.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 723 0 ) N ; ++ - read_p1_b4.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2343 0 ) N ; ++ - read_p1_b4.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 831 54 ) N ; ++ - read_p1_b4.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2343 54 ) N ; ++ - read_p1_b4.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 820 27 ) FS ; ++ - read_p1_b4.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2332 27 ) FS ; ++ - read_p1_b4.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 820 81 ) FS ; ++ - read_p1_b5.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 896 0 ) N ; ++ - read_p1_b5.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2516 0 ) N ; ++ - read_p1_b5.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1004 54 ) N ; ++ - read_p1_b5.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2516 54 ) N ; ++ - read_p1_b5.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 993 27 ) FS ; ++ - read_p1_b5.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2505 27 ) FS ; ++ - read_p1_b5.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 993 81 ) FS ; ++ - read_p1_b6.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1069 0 ) N ; ++ - read_p1_b6.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2689 0 ) N ; ++ - read_p1_b6.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1177 54 ) N ; ++ - read_p1_b6.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2689 54 ) N ; ++ - read_p1_b6.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1166 27 ) FS ; ++ - read_p1_b6.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2678 27 ) FS ; ++ - read_p1_b6.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1166 81 ) FS ; ++ - read_p1_b7.aoi_r0_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1242 0 ) N ; ++ - read_p1_b7.aoi_r0_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2862 0 ) N ; ++ - read_p1_b7.aoi_r2_w0 AOI22xp33_ASAP7_75t_R + PLACED ( 1350 54 ) N ; ++ - read_p1_b7.aoi_r2_w1 AOI22xp33_ASAP7_75t_R + PLACED ( 2862 54 ) N ; ++ - read_p1_b7.nand_r0_4 NAND2xp33_ASAP7_75t_R + PLACED ( 1339 27 ) FS ; ++ - read_p1_b7.nand_r4_8 NAND2xp33_ASAP7_75t_R + PLACED ( 2851 27 ) FS ; ++ - read_p1_b7.nor_r0_8 NOR2xp33_ASAP7_75t_R + PLACED ( 1339 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3196 0 ) N ; ++ - sel_buf_r_p1.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3218 0 ) N ; ++ - sel_buf_r_p1.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3196 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3218 27 ) FS ; ++ - sel_buf_r_p1.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3196 54 ) N ; ++ - sel_buf_r_p1.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3218 54 ) N ; ++ - sel_buf_r_p1.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3196 81 ) FS ; ++ - sel_buf_r_p1.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3218 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3369 0 ) N ; ++ - sel_buf_r_p2.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3391 0 ) N ; ++ - sel_buf_r_p2.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3369 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3391 27 ) FS ; ++ - sel_buf_r_p2.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3369 54 ) N ; ++ - sel_buf_r_p2.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3391 54 ) N ; ++ - sel_buf_r_p2.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3369 81 ) FS ; ++ - sel_buf_r_p2.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3391 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_0 HB1xp67_ASAP7_75t_R + PLACED ( 3024 0 ) N ; ++ - sel_buf_w_p0.sel_buf_1 HB1xp67_ASAP7_75t_R + PLACED ( 3045 0 ) N ; ++ - sel_buf_w_p0.sel_buf_2 HB1xp67_ASAP7_75t_R + PLACED ( 3024 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_3 HB1xp67_ASAP7_75t_R + PLACED ( 3045 27 ) FS ; ++ - sel_buf_w_p0.sel_buf_4 HB1xp67_ASAP7_75t_R + PLACED ( 3024 54 ) N ; ++ - sel_buf_w_p0.sel_buf_5 HB1xp67_ASAP7_75t_R + PLACED ( 3045 54 ) N ; ++ - sel_buf_w_p0.sel_buf_6 HB1xp67_ASAP7_75t_R + PLACED ( 3024 81 ) FS ; ++ - sel_buf_w_p0.sel_buf_7 HB1xp67_ASAP7_75t_R + PLACED ( 3045 81 ) FS ; ++ - storage_0_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1512 0 ) N ; ++ - storage_0_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1684 0 ) N ; ++ - storage_0_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1857 0 ) N ; ++ - storage_0_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2030 0 ) N ; ++ - storage_0_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2203 0 ) N ; ++ - storage_0_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2376 0 ) N ; ++ - storage_0_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2548 0 ) N ; ++ - storage_0_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2721 0 ) N ; ++ - storage_0_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 0 ) N ; ++ - storage_0_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 0 ) N ; ++ - storage_1_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 27 ) FS ; ++ - storage_1_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 27 ) FS ; ++ - storage_1_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 27 ) FS ; ++ - storage_1_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 27 ) FS ; ++ - storage_1_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 27 ) FS ; ++ - storage_1_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 27 ) FS ; ++ - storage_1_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 27 ) FS ; ++ - storage_1_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 27 ) FS ; ++ - storage_1_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 27 ) FS ; ++ - storage_1_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 27 ) FS ; ++ - storage_1_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1512 27 ) FS ; ++ - storage_1_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1684 27 ) FS ; ++ - storage_1_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1857 27 ) FS ; ++ - storage_1_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2030 27 ) FS ; ++ - storage_1_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2203 27 ) FS ; ++ - storage_1_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2376 27 ) FS ; ++ - storage_1_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2548 27 ) FS ; ++ - storage_1_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2721 27 ) FS ; ++ - storage_1_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 27 ) FS ; ++ - storage_1_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 27 ) FS ; ++ - storage_2_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 54 ) N ; ++ - storage_2_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 54 ) N ; ++ - storage_2_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 54 ) N ; ++ - storage_2_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 54 ) N ; ++ - storage_2_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 54 ) N ; ++ - storage_2_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 54 ) N ; ++ - storage_2_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 54 ) N ; ++ - storage_2_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 54 ) N ; ++ - storage_2_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 54 ) N ; ++ - storage_2_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 54 ) N ; ++ - storage_2_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1512 54 ) N ; ++ - storage_2_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1684 54 ) N ; ++ - storage_2_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1857 54 ) N ; ++ - storage_2_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2030 54 ) N ; ++ - storage_2_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2203 54 ) N ; ++ - storage_2_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2376 54 ) N ; ++ - storage_2_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2548 54 ) N ; ++ - storage_2_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2721 54 ) N ; ++ - storage_2_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 54 ) N ; ++ - storage_2_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 54 ) N ; ++ - storage_3_0_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 0 81 ) FS ; ++ - storage_3_0_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 172 81 ) FS ; ++ - storage_3_0_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 345 81 ) FS ; ++ - storage_3_0_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 518 81 ) FS ; ++ - storage_3_0_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 691 81 ) FS ; ++ - storage_3_0_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 864 81 ) FS ; ++ - storage_3_0_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1036 81 ) FS ; ++ - storage_3_0_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1209 81 ) FS ; ++ - storage_3_0_0.cg ICGx1_ASAP7_75t_R + PLACED ( 1382 81 ) FS ; ++ - storage_3_0_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 1479 81 ) FS ; ++ - storage_3_1_0.bit0.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1512 81 ) FS ; ++ - storage_3_1_0.bit1.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1684 81 ) FS ; ++ - storage_3_1_0.bit2.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 1857 81 ) FS ; ++ - storage_3_1_0.bit3.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2030 81 ) FS ; ++ - storage_3_1_0.bit4.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2203 81 ) FS ; ++ - storage_3_1_0.bit5.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2376 81 ) FS ; ++ - storage_3_1_0.bit6.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2548 81 ) FS ; ++ - storage_3_1_0.bit7.bit DFFHQNx1_ASAP7_75t_R + PLACED ( 2721 81 ) FS ; ++ - storage_3_1_0.cg ICGx1_ASAP7_75t_R + PLACED ( 2894 81 ) FS ; ++ - storage_3_1_0.gcand AND2x2_ASAP7_75t_R + PLACED ( 2991 81 ) FS ; ++END COMPONENTS ++PINS 35 ; ++ - D[0] + NET D[0] + DIRECTION INPUT + USE SIGNAL ; ++ - D[1] + NET D[1] + DIRECTION INPUT + USE SIGNAL ; ++ - D[2] + NET D[2] + DIRECTION INPUT + USE SIGNAL ; ++ - D[3] + NET D[3] + DIRECTION INPUT + USE SIGNAL ; ++ - D[4] + NET D[4] + DIRECTION INPUT + USE SIGNAL ; ++ - D[5] + NET D[5] + DIRECTION INPUT + USE SIGNAL ; ++ - D[6] + NET D[6] + DIRECTION INPUT + USE SIGNAL ; ++ - D[7] + NET D[7] + DIRECTION INPUT + USE SIGNAL ; ++ - Q0[0] + NET Q0[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[1] + NET Q0[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[2] + NET Q0[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[3] + NET Q0[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[4] + NET Q0[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[5] + NET Q0[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[6] + NET Q0[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q0[7] + NET Q0[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[0] + NET Q1[0] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[1] + NET Q1[1] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[2] + NET Q1[2] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[3] + NET Q1[3] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[4] + NET Q1[4] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[5] + NET Q1[5] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[6] + NET Q1[6] + DIRECTION OUTPUT + USE SIGNAL ; ++ - Q1[7] + NET Q1[7] + DIRECTION OUTPUT + USE SIGNAL ; ++ - addr_r0[0] + NET addr_r0[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[1] + NET addr_r0[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r0[2] + NET addr_r0[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[0] + NET addr_r1[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[1] + NET addr_r1[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_r1[2] + NET addr_r1[2] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[0] + NET addr_w[0] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[1] + NET addr_w[1] + DIRECTION INPUT + USE SIGNAL ; ++ - addr_w[2] + NET addr_w[2] + DIRECTION INPUT + USE SIGNAL ; ++ - clk + NET clk + DIRECTION INPUT + USE SIGNAL ; ++ - we[0] + NET we[0] + DIRECTION INPUT + USE SIGNAL ; ++END PINS ++NETS 290 ; ++ - D[0] ( PIN D[0] ) ( buffer.in[0] A ) + USE SIGNAL ; ++ - D[1] ( PIN D[1] ) ( buffer.in[1] A ) + USE SIGNAL ; ++ - D[2] ( PIN D[2] ) ( buffer.in[2] A ) + USE SIGNAL ; ++ - D[3] ( PIN D[3] ) ( buffer.in[3] A ) + USE SIGNAL ; ++ - D[4] ( PIN D[4] ) ( buffer.in[4] A ) + USE SIGNAL ; ++ - D[5] ( PIN D[5] ) ( buffer.in[5] A ) + USE SIGNAL ; ++ - D[6] ( PIN D[6] ) ( buffer.in[6] A ) + USE SIGNAL ; ++ - D[7] ( PIN D[7] ) ( buffer.in[7] A ) + USE SIGNAL ; ++ - D_nets.b0 ( buffer.in[0] Y ) ( storage_3_1_0.bit0.bit D ) ( storage_3_0_0.bit0.bit D ) ( storage_2_1_0.bit0.bit D ) ( storage_2_0_0.bit0.bit D ) ( storage_1_1_0.bit0.bit D ) ( storage_1_0_0.bit0.bit D ) ++ ( storage_0_1_0.bit0.bit D ) + USE SIGNAL ; ++ - D_nets.b1 ( buffer.in[1] Y ) ( storage_3_1_0.bit1.bit D ) ( storage_3_0_0.bit1.bit D ) ( storage_2_1_0.bit1.bit D ) ( storage_2_0_0.bit1.bit D ) ( storage_1_1_0.bit1.bit D ) ( storage_1_0_0.bit1.bit D ) ++ ( storage_0_1_0.bit1.bit D ) + USE SIGNAL ; ++ - D_nets.b2 ( buffer.in[2] Y ) ( storage_3_1_0.bit2.bit D ) ( storage_3_0_0.bit2.bit D ) ( storage_2_1_0.bit2.bit D ) ( storage_2_0_0.bit2.bit D ) ( storage_1_1_0.bit2.bit D ) ( storage_1_0_0.bit2.bit D ) ++ ( storage_0_1_0.bit2.bit D ) + USE SIGNAL ; ++ - D_nets.b3 ( buffer.in[3] Y ) ( storage_3_1_0.bit3.bit D ) ( storage_3_0_0.bit3.bit D ) ( storage_2_1_0.bit3.bit D ) ( storage_2_0_0.bit3.bit D ) ( storage_1_1_0.bit3.bit D ) ( storage_1_0_0.bit3.bit D ) ++ ( storage_0_1_0.bit3.bit D ) + USE SIGNAL ; ++ - D_nets.b4 ( buffer.in[4] Y ) ( storage_3_1_0.bit4.bit D ) ( storage_3_0_0.bit4.bit D ) ( storage_2_1_0.bit4.bit D ) ( storage_2_0_0.bit4.bit D ) ( storage_1_1_0.bit4.bit D ) ( storage_1_0_0.bit4.bit D ) ++ ( storage_0_1_0.bit4.bit D ) + USE SIGNAL ; ++ - D_nets.b5 ( buffer.in[5] Y ) ( storage_3_1_0.bit5.bit D ) ( storage_3_0_0.bit5.bit D ) ( storage_2_1_0.bit5.bit D ) ( storage_2_0_0.bit5.bit D ) ( storage_1_1_0.bit5.bit D ) ( storage_1_0_0.bit5.bit D ) ++ ( storage_0_1_0.bit5.bit D ) + USE SIGNAL ; ++ - D_nets.b6 ( buffer.in[6] Y ) ( storage_3_1_0.bit6.bit D ) ( storage_3_0_0.bit6.bit D ) ( storage_2_1_0.bit6.bit D ) ( storage_2_0_0.bit6.bit D ) ( storage_1_1_0.bit6.bit D ) ( storage_1_0_0.bit6.bit D ) ++ ( storage_0_1_0.bit6.bit D ) + USE SIGNAL ; ++ - D_nets.b7 ( buffer.in[7] Y ) ( storage_3_1_0.bit7.bit D ) ( storage_3_0_0.bit7.bit D ) ( storage_2_1_0.bit7.bit D ) ( storage_2_0_0.bit7.bit D ) ( storage_1_1_0.bit7.bit D ) ( storage_1_0_0.bit7.bit D ) ++ ( storage_0_1_0.bit7.bit D ) + USE SIGNAL ; ++ - Q0[0] ( PIN Q0[0] ) ( read_p0_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[1] ( PIN Q0[1] ) ( read_p0_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[2] ( PIN Q0[2] ) ( read_p0_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[3] ( PIN Q0[3] ) ( read_p0_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[4] ( PIN Q0[4] ) ( read_p0_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[5] ( PIN Q0[5] ) ( read_p0_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[6] ( PIN Q0[6] ) ( read_p0_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q0[7] ( PIN Q0[7] ) ( read_p0_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[0] ( PIN Q1[0] ) ( read_p1_b0.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[1] ( PIN Q1[1] ) ( read_p1_b1.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[2] ( PIN Q1[2] ) ( read_p1_b2.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[3] ( PIN Q1[3] ) ( read_p1_b3.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[4] ( PIN Q1[4] ) ( read_p1_b4.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[5] ( PIN Q1[5] ) ( read_p1_b5.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[6] ( PIN Q1[6] ) ( read_p1_b6.nor_r0_8 Y ) + USE SIGNAL ; ++ - Q1[7] ( PIN Q1[7] ) ( read_p1_b7.nor_r0_8 Y ) + USE SIGNAL ; ++ - addr_r0.inv_addr[0] ( decoder_p1.inv_p1_a0 Y ) ( decoder_p1.and0_word6 A ) ( decoder_p1.and0_word4 A ) ( decoder_p1.and0_word2 A ) ( decoder_p1.and0_word0 A ) + USE SIGNAL ; ++ - addr_r0.inv_addr[1] ( decoder_p1.inv_p1_a1 Y ) ( decoder_p1.and0_word3 B ) ( decoder_p1.and0_word2 B ) ( decoder_p1.and0_word1 B ) ( decoder_p1.and0_word0 B ) + USE SIGNAL ; ++ - addr_r0.inv_addr[2] ( decoder_p1.inv_p1_a2 Y ) ( decoder_p1.and1_word5 B ) ( decoder_p1.and1_word4 B ) ( decoder_p1.and1_word1 B ) ( decoder_p1.and1_word0 B ) + USE SIGNAL ; ++ - addr_r0[0] ( PIN addr_r0[0] ) ( decoder_p1.inv_p1_a0 A ) ( decoder_p1.and0_word7 A ) ( decoder_p1.and0_word5 A ) ( decoder_p1.and0_word3 A ) ( decoder_p1.and0_word1 A ) + USE SIGNAL ; ++ - addr_r0[1] ( PIN addr_r0[1] ) ( decoder_p1.inv_p1_a1 A ) ( decoder_p1.and0_word7 B ) ( decoder_p1.and0_word6 B ) ( decoder_p1.and0_word5 B ) ( decoder_p1.and0_word4 B ) + USE SIGNAL ; ++ - addr_r0[2] ( PIN addr_r0[2] ) ( decoder_p1.inv_p1_a2 A ) ( decoder_p1.and1_word7 B ) ( decoder_p1.and1_word6 B ) ( decoder_p1.and1_word3 B ) ( decoder_p1.and1_word2 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[0] ( decoder_p2.inv_p2_a0 Y ) ( decoder_p2.and0_word6 A ) ( decoder_p2.and0_word4 A ) ( decoder_p2.and0_word2 A ) ( decoder_p2.and0_word0 A ) + USE SIGNAL ; ++ - addr_r1.inv_addr[1] ( decoder_p2.inv_p2_a1 Y ) ( decoder_p2.and0_word3 B ) ( decoder_p2.and0_word2 B ) ( decoder_p2.and0_word1 B ) ( decoder_p2.and0_word0 B ) + USE SIGNAL ; ++ - addr_r1.inv_addr[2] ( decoder_p2.inv_p2_a2 Y ) ( decoder_p2.and1_word5 B ) ( decoder_p2.and1_word4 B ) ( decoder_p2.and1_word1 B ) ( decoder_p2.and1_word0 B ) + USE SIGNAL ; ++ - addr_r1[0] ( PIN addr_r1[0] ) ( decoder_p2.inv_p2_a0 A ) ( decoder_p2.and0_word7 A ) ( decoder_p2.and0_word5 A ) ( decoder_p2.and0_word3 A ) ( decoder_p2.and0_word1 A ) + USE SIGNAL ; ++ - addr_r1[1] ( PIN addr_r1[1] ) ( decoder_p2.inv_p2_a1 A ) ( decoder_p2.and0_word7 B ) ( decoder_p2.and0_word6 B ) ( decoder_p2.and0_word5 B ) ( decoder_p2.and0_word4 B ) + USE SIGNAL ; ++ - addr_r1[2] ( PIN addr_r1[2] ) ( decoder_p2.inv_p2_a2 A ) ( decoder_p2.and1_word7 B ) ( decoder_p2.and1_word6 B ) ( decoder_p2.and1_word3 B ) ( decoder_p2.and1_word2 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[0] ( decoder_p0.inv_p0_a0 Y ) ( decoder_p0.and0_word6 A ) ( decoder_p0.and0_word4 A ) ( decoder_p0.and0_word2 A ) ( decoder_p0.and0_word0 A ) + USE SIGNAL ; ++ - addr_w.inv_addr[1] ( decoder_p0.inv_p0_a1 Y ) ( decoder_p0.and0_word3 B ) ( decoder_p0.and0_word2 B ) ( decoder_p0.and0_word1 B ) ( decoder_p0.and0_word0 B ) + USE SIGNAL ; ++ - addr_w.inv_addr[2] ( decoder_p0.inv_p0_a2 Y ) ( decoder_p0.and1_word5 B ) ( decoder_p0.and1_word4 B ) ( decoder_p0.and1_word1 B ) ( decoder_p0.and1_word0 B ) + USE SIGNAL ; ++ - addr_w[0] ( PIN addr_w[0] ) ( decoder_p0.inv_p0_a0 A ) ( decoder_p0.and0_word7 A ) ( decoder_p0.and0_word5 A ) ( decoder_p0.and0_word3 A ) ( decoder_p0.and0_word1 A ) + USE SIGNAL ; ++ - addr_w[1] ( PIN addr_w[1] ) ( decoder_p0.inv_p0_a1 A ) ( decoder_p0.and0_word7 B ) ( decoder_p0.and0_word6 B ) ( decoder_p0.and0_word5 B ) ( decoder_p0.and0_word4 B ) + USE SIGNAL ; ++ - addr_w[2] ( PIN addr_w[2] ) ( decoder_p0.inv_p0_a2 A ) ( decoder_p0.and1_word7 B ) ( decoder_p0.and1_word6 B ) ( decoder_p0.and1_word3 B ) ( decoder_p0.and1_word2 B ) + USE SIGNAL ; ++ - clk ( PIN clk ) ( storage_3_1_0.cg CLK ) ( storage_3_0_0.cg CLK ) ( storage_2_1_0.cg CLK ) ( storage_2_0_0.cg CLK ) ( storage_1_1_0.cg CLK ) ( storage_1_0_0.cg CLK ) ++ ( storage_0_1_0.cg CLK ) + USE SIGNAL ; ++ - decoder_p0.word0 ( decoder_p0.and1_word0 Y ) ( sel_buf_w_p0.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p0.word1 ( decoder_p0.and1_word1 Y ) ( sel_buf_w_p0.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p0.word2 ( decoder_p0.and1_word2 Y ) ( sel_buf_w_p0.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p0.word3 ( decoder_p0.and1_word3 Y ) ( sel_buf_w_p0.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p0.word4 ( decoder_p0.and1_word4 Y ) ( sel_buf_w_p0.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p0.word5 ( decoder_p0.and1_word5 Y ) ( sel_buf_w_p0.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p0.word6 ( decoder_p0.and1_word6 Y ) ( sel_buf_w_p0.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p0.word7 ( decoder_p0.and1_word7 Y ) ( sel_buf_w_p0.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p0.y0_word0 ( decoder_p0.and1_word0 A ) ( decoder_p0.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word1 ( decoder_p0.and1_word1 A ) ( decoder_p0.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word2 ( decoder_p0.and1_word2 A ) ( decoder_p0.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word3 ( decoder_p0.and1_word3 A ) ( decoder_p0.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word4 ( decoder_p0.and1_word4 A ) ( decoder_p0.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word5 ( decoder_p0.and1_word5 A ) ( decoder_p0.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word6 ( decoder_p0.and1_word6 A ) ( decoder_p0.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p0.y0_word7 ( decoder_p0.and1_word7 A ) ( decoder_p0.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p1.word0 ( decoder_p1.and1_word0 Y ) ( sel_buf_r_p1.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p1.word1 ( decoder_p1.and1_word1 Y ) ( sel_buf_r_p1.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p1.word2 ( decoder_p1.and1_word2 Y ) ( sel_buf_r_p1.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p1.word3 ( decoder_p1.and1_word3 Y ) ( sel_buf_r_p1.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p1.word4 ( decoder_p1.and1_word4 Y ) ( sel_buf_r_p1.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p1.word5 ( decoder_p1.and1_word5 Y ) ( sel_buf_r_p1.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p1.word6 ( decoder_p1.and1_word6 Y ) ( sel_buf_r_p1.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p1.word7 ( decoder_p1.and1_word7 Y ) ( sel_buf_r_p1.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p1.y0_word0 ( decoder_p1.and1_word0 A ) ( decoder_p1.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word1 ( decoder_p1.and1_word1 A ) ( decoder_p1.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word2 ( decoder_p1.and1_word2 A ) ( decoder_p1.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word3 ( decoder_p1.and1_word3 A ) ( decoder_p1.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word4 ( decoder_p1.and1_word4 A ) ( decoder_p1.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word5 ( decoder_p1.and1_word5 A ) ( decoder_p1.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word6 ( decoder_p1.and1_word6 A ) ( decoder_p1.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p1.y0_word7 ( decoder_p1.and1_word7 A ) ( decoder_p1.and0_word7 Y ) + USE SIGNAL ; ++ - decoder_p2.word0 ( decoder_p2.and1_word0 Y ) ( sel_buf_r_p2.sel_buf_0 A ) + USE SIGNAL ; ++ - decoder_p2.word1 ( decoder_p2.and1_word1 Y ) ( sel_buf_r_p2.sel_buf_1 A ) + USE SIGNAL ; ++ - decoder_p2.word2 ( decoder_p2.and1_word2 Y ) ( sel_buf_r_p2.sel_buf_2 A ) + USE SIGNAL ; ++ - decoder_p2.word3 ( decoder_p2.and1_word3 Y ) ( sel_buf_r_p2.sel_buf_3 A ) + USE SIGNAL ; ++ - decoder_p2.word4 ( decoder_p2.and1_word4 Y ) ( sel_buf_r_p2.sel_buf_4 A ) + USE SIGNAL ; ++ - decoder_p2.word5 ( decoder_p2.and1_word5 Y ) ( sel_buf_r_p2.sel_buf_5 A ) + USE SIGNAL ; ++ - decoder_p2.word6 ( decoder_p2.and1_word6 Y ) ( sel_buf_r_p2.sel_buf_6 A ) + USE SIGNAL ; ++ - decoder_p2.word7 ( decoder_p2.and1_word7 Y ) ( sel_buf_r_p2.sel_buf_7 A ) + USE SIGNAL ; ++ - decoder_p2.y0_word0 ( decoder_p2.and1_word0 A ) ( decoder_p2.and0_word0 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word1 ( decoder_p2.and1_word1 A ) ( decoder_p2.and0_word1 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word2 ( decoder_p2.and1_word2 A ) ( decoder_p2.and0_word2 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word3 ( decoder_p2.and1_word3 A ) ( decoder_p2.and0_word3 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word4 ( decoder_p2.and1_word4 A ) ( decoder_p2.and0_word4 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word5 ( decoder_p2.and1_word5 A ) ( decoder_p2.and0_word5 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word6 ( decoder_p2.and1_word6 A ) ( decoder_p2.and0_word6 Y ) + USE SIGNAL ; ++ - decoder_p2.y0_word7 ( decoder_p2.and1_word7 A ) ( decoder_p2.and0_word7 Y ) + USE SIGNAL ; ++ - r_sel_p1.select_r0 ( sel_buf_r_p1.sel_buf_0 Y ) ( read_p0_b7.aoi_r0_w0 A2 ) ( read_p0_b7.aoi_r0_w0 A1 ) ( read_p0_b6.aoi_r0_w0 A2 ) ( read_p0_b6.aoi_r0_w0 A1 ) ( read_p0_b5.aoi_r0_w0 A2 ) ( read_p0_b5.aoi_r0_w0 A1 ) ++ ( read_p0_b4.aoi_r0_w0 A2 ) ( read_p0_b4.aoi_r0_w0 A1 ) ( read_p0_b3.aoi_r0_w0 A2 ) ( read_p0_b3.aoi_r0_w0 A1 ) ( read_p0_b2.aoi_r0_w0 A2 ) ( read_p0_b2.aoi_r0_w0 A1 ) ( read_p0_b1.aoi_r0_w0 A2 ) ( read_p0_b1.aoi_r0_w0 A1 ) ++ ( read_p0_b0.aoi_r0_w0 A2 ) ( read_p0_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r1 ( sel_buf_r_p1.sel_buf_1 Y ) ( read_p0_b7.aoi_r0_w1 A1 ) ( read_p0_b6.aoi_r0_w1 A1 ) ( read_p0_b5.aoi_r0_w1 A1 ) ( read_p0_b4.aoi_r0_w1 A1 ) ( read_p0_b3.aoi_r0_w1 A1 ) ( read_p0_b2.aoi_r0_w1 A1 ) ++ ( read_p0_b1.aoi_r0_w1 A1 ) ( read_p0_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r2 ( sel_buf_r_p1.sel_buf_2 Y ) ( read_p0_b7.aoi_r0_w0 B1 ) ( read_p0_b6.aoi_r0_w0 B1 ) ( read_p0_b5.aoi_r0_w0 B1 ) ( read_p0_b4.aoi_r0_w0 B1 ) ( read_p0_b3.aoi_r0_w0 B1 ) ( read_p0_b2.aoi_r0_w0 B1 ) ++ ( read_p0_b1.aoi_r0_w0 B1 ) ( read_p0_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r3 ( sel_buf_r_p1.sel_buf_3 Y ) ( read_p0_b7.aoi_r0_w1 B1 ) ( read_p0_b6.aoi_r0_w1 B1 ) ( read_p0_b5.aoi_r0_w1 B1 ) ( read_p0_b4.aoi_r0_w1 B1 ) ( read_p0_b3.aoi_r0_w1 B1 ) ( read_p0_b2.aoi_r0_w1 B1 ) ++ ( read_p0_b1.aoi_r0_w1 B1 ) ( read_p0_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r4 ( sel_buf_r_p1.sel_buf_4 Y ) ( read_p0_b7.aoi_r2_w0 A1 ) ( read_p0_b6.aoi_r2_w0 A1 ) ( read_p0_b5.aoi_r2_w0 A1 ) ( read_p0_b4.aoi_r2_w0 A1 ) ( read_p0_b3.aoi_r2_w0 A1 ) ( read_p0_b2.aoi_r2_w0 A1 ) ++ ( read_p0_b1.aoi_r2_w0 A1 ) ( read_p0_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r5 ( sel_buf_r_p1.sel_buf_5 Y ) ( read_p0_b7.aoi_r2_w1 A1 ) ( read_p0_b6.aoi_r2_w1 A1 ) ( read_p0_b5.aoi_r2_w1 A1 ) ( read_p0_b4.aoi_r2_w1 A1 ) ( read_p0_b3.aoi_r2_w1 A1 ) ( read_p0_b2.aoi_r2_w1 A1 ) ++ ( read_p0_b1.aoi_r2_w1 A1 ) ( read_p0_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r6 ( sel_buf_r_p1.sel_buf_6 Y ) ( read_p0_b7.aoi_r2_w0 B1 ) ( read_p0_b6.aoi_r2_w0 B1 ) ( read_p0_b5.aoi_r2_w0 B1 ) ( read_p0_b4.aoi_r2_w0 B1 ) ( read_p0_b3.aoi_r2_w0 B1 ) ( read_p0_b2.aoi_r2_w0 B1 ) ++ ( read_p0_b1.aoi_r2_w0 B1 ) ( read_p0_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p1.select_r7 ( sel_buf_r_p1.sel_buf_7 Y ) ( read_p0_b7.aoi_r2_w1 B1 ) ( read_p0_b6.aoi_r2_w1 B1 ) ( read_p0_b5.aoi_r2_w1 B1 ) ( read_p0_b4.aoi_r2_w1 B1 ) ( read_p0_b3.aoi_r2_w1 B1 ) ( read_p0_b2.aoi_r2_w1 B1 ) ++ ( read_p0_b1.aoi_r2_w1 B1 ) ( read_p0_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r0 ( sel_buf_r_p2.sel_buf_0 Y ) ( read_p1_b7.aoi_r0_w0 A2 ) ( read_p1_b7.aoi_r0_w0 A1 ) ( read_p1_b6.aoi_r0_w0 A2 ) ( read_p1_b6.aoi_r0_w0 A1 ) ( read_p1_b5.aoi_r0_w0 A2 ) ( read_p1_b5.aoi_r0_w0 A1 ) ++ ( read_p1_b4.aoi_r0_w0 A2 ) ( read_p1_b4.aoi_r0_w0 A1 ) ( read_p1_b3.aoi_r0_w0 A2 ) ( read_p1_b3.aoi_r0_w0 A1 ) ( read_p1_b2.aoi_r0_w0 A2 ) ( read_p1_b2.aoi_r0_w0 A1 ) ( read_p1_b1.aoi_r0_w0 A2 ) ( read_p1_b1.aoi_r0_w0 A1 ) ++ ( read_p1_b0.aoi_r0_w0 A2 ) ( read_p1_b0.aoi_r0_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r1 ( sel_buf_r_p2.sel_buf_1 Y ) ( read_p1_b7.aoi_r0_w1 A1 ) ( read_p1_b6.aoi_r0_w1 A1 ) ( read_p1_b5.aoi_r0_w1 A1 ) ( read_p1_b4.aoi_r0_w1 A1 ) ( read_p1_b3.aoi_r0_w1 A1 ) ( read_p1_b2.aoi_r0_w1 A1 ) ++ ( read_p1_b1.aoi_r0_w1 A1 ) ( read_p1_b0.aoi_r0_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r2 ( sel_buf_r_p2.sel_buf_2 Y ) ( read_p1_b7.aoi_r0_w0 B1 ) ( read_p1_b6.aoi_r0_w0 B1 ) ( read_p1_b5.aoi_r0_w0 B1 ) ( read_p1_b4.aoi_r0_w0 B1 ) ( read_p1_b3.aoi_r0_w0 B1 ) ( read_p1_b2.aoi_r0_w0 B1 ) ++ ( read_p1_b1.aoi_r0_w0 B1 ) ( read_p1_b0.aoi_r0_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r3 ( sel_buf_r_p2.sel_buf_3 Y ) ( read_p1_b7.aoi_r0_w1 B1 ) ( read_p1_b6.aoi_r0_w1 B1 ) ( read_p1_b5.aoi_r0_w1 B1 ) ( read_p1_b4.aoi_r0_w1 B1 ) ( read_p1_b3.aoi_r0_w1 B1 ) ( read_p1_b2.aoi_r0_w1 B1 ) ++ ( read_p1_b1.aoi_r0_w1 B1 ) ( read_p1_b0.aoi_r0_w1 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r4 ( sel_buf_r_p2.sel_buf_4 Y ) ( read_p1_b7.aoi_r2_w0 A1 ) ( read_p1_b6.aoi_r2_w0 A1 ) ( read_p1_b5.aoi_r2_w0 A1 ) ( read_p1_b4.aoi_r2_w0 A1 ) ( read_p1_b3.aoi_r2_w0 A1 ) ( read_p1_b2.aoi_r2_w0 A1 ) ++ ( read_p1_b1.aoi_r2_w0 A1 ) ( read_p1_b0.aoi_r2_w0 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r5 ( sel_buf_r_p2.sel_buf_5 Y ) ( read_p1_b7.aoi_r2_w1 A1 ) ( read_p1_b6.aoi_r2_w1 A1 ) ( read_p1_b5.aoi_r2_w1 A1 ) ( read_p1_b4.aoi_r2_w1 A1 ) ( read_p1_b3.aoi_r2_w1 A1 ) ( read_p1_b2.aoi_r2_w1 A1 ) ++ ( read_p1_b1.aoi_r2_w1 A1 ) ( read_p1_b0.aoi_r2_w1 A1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r6 ( sel_buf_r_p2.sel_buf_6 Y ) ( read_p1_b7.aoi_r2_w0 B1 ) ( read_p1_b6.aoi_r2_w0 B1 ) ( read_p1_b5.aoi_r2_w0 B1 ) ( read_p1_b4.aoi_r2_w0 B1 ) ( read_p1_b3.aoi_r2_w0 B1 ) ( read_p1_b2.aoi_r2_w0 B1 ) ++ ( read_p1_b1.aoi_r2_w0 B1 ) ( read_p1_b0.aoi_r2_w0 B1 ) + USE SIGNAL ; ++ - r_sel_p2.select_r7 ( sel_buf_r_p2.sel_buf_7 Y ) ( read_p1_b7.aoi_r2_w1 B1 ) ( read_p1_b6.aoi_r2_w1 B1 ) ( read_p1_b5.aoi_r2_w1 B1 ) ( read_p1_b4.aoi_r2_w1 B1 ) ( read_p1_b3.aoi_r2_w1 B1 ) ( read_p1_b2.aoi_r2_w1 B1 ) ++ ( read_p1_b1.aoi_r2_w1 B1 ) ( read_p1_b0.aoi_r2_w1 B1 ) + USE SIGNAL ; ++ - read_p0_b0.t0_2 ( read_p0_b0.nand_r0_4 A ) ( read_p0_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b0.t0_4 ( read_p0_b0.nor_r0_8 A ) ( read_p0_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b0.t2_4 ( read_p0_b0.aoi_r2_w0 Y ) ( read_p0_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b0.t4_6 ( read_p0_b0.nand_r4_8 A ) ( read_p0_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b0.t4_8 ( read_p0_b0.nor_r0_8 B ) ( read_p0_b0.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b0.t6_8 ( read_p0_b0.aoi_r2_w1 Y ) ( read_p0_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b1.t0_2 ( read_p0_b1.nand_r0_4 A ) ( read_p0_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b1.t0_4 ( read_p0_b1.nor_r0_8 A ) ( read_p0_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b1.t2_4 ( read_p0_b1.aoi_r2_w0 Y ) ( read_p0_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b1.t4_6 ( read_p0_b1.nand_r4_8 A ) ( read_p0_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b1.t4_8 ( read_p0_b1.nor_r0_8 B ) ( read_p0_b1.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b1.t6_8 ( read_p0_b1.aoi_r2_w1 Y ) ( read_p0_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b2.t0_2 ( read_p0_b2.nand_r0_4 A ) ( read_p0_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b2.t0_4 ( read_p0_b2.nor_r0_8 A ) ( read_p0_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b2.t2_4 ( read_p0_b2.aoi_r2_w0 Y ) ( read_p0_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b2.t4_6 ( read_p0_b2.nand_r4_8 A ) ( read_p0_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b2.t4_8 ( read_p0_b2.nor_r0_8 B ) ( read_p0_b2.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b2.t6_8 ( read_p0_b2.aoi_r2_w1 Y ) ( read_p0_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b3.t0_2 ( read_p0_b3.nand_r0_4 A ) ( read_p0_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b3.t0_4 ( read_p0_b3.nor_r0_8 A ) ( read_p0_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b3.t2_4 ( read_p0_b3.aoi_r2_w0 Y ) ( read_p0_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b3.t4_6 ( read_p0_b3.nand_r4_8 A ) ( read_p0_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b3.t4_8 ( read_p0_b3.nor_r0_8 B ) ( read_p0_b3.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b3.t6_8 ( read_p0_b3.aoi_r2_w1 Y ) ( read_p0_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b4.t0_2 ( read_p0_b4.nand_r0_4 A ) ( read_p0_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b4.t0_4 ( read_p0_b4.nor_r0_8 A ) ( read_p0_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b4.t2_4 ( read_p0_b4.aoi_r2_w0 Y ) ( read_p0_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b4.t4_6 ( read_p0_b4.nand_r4_8 A ) ( read_p0_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b4.t4_8 ( read_p0_b4.nor_r0_8 B ) ( read_p0_b4.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b4.t6_8 ( read_p0_b4.aoi_r2_w1 Y ) ( read_p0_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b5.t0_2 ( read_p0_b5.nand_r0_4 A ) ( read_p0_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b5.t0_4 ( read_p0_b5.nor_r0_8 A ) ( read_p0_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b5.t2_4 ( read_p0_b5.aoi_r2_w0 Y ) ( read_p0_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b5.t4_6 ( read_p0_b5.nand_r4_8 A ) ( read_p0_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b5.t4_8 ( read_p0_b5.nor_r0_8 B ) ( read_p0_b5.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b5.t6_8 ( read_p0_b5.aoi_r2_w1 Y ) ( read_p0_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b6.t0_2 ( read_p0_b6.nand_r0_4 A ) ( read_p0_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b6.t0_4 ( read_p0_b6.nor_r0_8 A ) ( read_p0_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b6.t2_4 ( read_p0_b6.aoi_r2_w0 Y ) ( read_p0_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b6.t4_6 ( read_p0_b6.nand_r4_8 A ) ( read_p0_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b6.t4_8 ( read_p0_b6.nor_r0_8 B ) ( read_p0_b6.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b6.t6_8 ( read_p0_b6.aoi_r2_w1 Y ) ( read_p0_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p0_b7.t0_2 ( read_p0_b7.nand_r0_4 A ) ( read_p0_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p0_b7.t0_4 ( read_p0_b7.nor_r0_8 A ) ( read_p0_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p0_b7.t2_4 ( read_p0_b7.aoi_r2_w0 Y ) ( read_p0_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p0_b7.t4_6 ( read_p0_b7.nand_r4_8 A ) ( read_p0_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p0_b7.t4_8 ( read_p0_b7.nor_r0_8 B ) ( read_p0_b7.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p0_b7.t6_8 ( read_p0_b7.aoi_r2_w1 Y ) ( read_p0_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b0.t0_2 ( read_p1_b0.nand_r0_4 A ) ( read_p1_b0.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b0.t0_4 ( read_p1_b0.nor_r0_8 A ) ( read_p1_b0.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b0.t2_4 ( read_p1_b0.aoi_r2_w0 Y ) ( read_p1_b0.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b0.t4_6 ( read_p1_b0.nand_r4_8 A ) ( read_p1_b0.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b0.t4_8 ( read_p1_b0.nor_r0_8 B ) ( read_p1_b0.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b0.t6_8 ( read_p1_b0.aoi_r2_w1 Y ) ( read_p1_b0.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b1.t0_2 ( read_p1_b1.nand_r0_4 A ) ( read_p1_b1.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b1.t0_4 ( read_p1_b1.nor_r0_8 A ) ( read_p1_b1.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b1.t2_4 ( read_p1_b1.aoi_r2_w0 Y ) ( read_p1_b1.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b1.t4_6 ( read_p1_b1.nand_r4_8 A ) ( read_p1_b1.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b1.t4_8 ( read_p1_b1.nor_r0_8 B ) ( read_p1_b1.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b1.t6_8 ( read_p1_b1.aoi_r2_w1 Y ) ( read_p1_b1.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b2.t0_2 ( read_p1_b2.nand_r0_4 A ) ( read_p1_b2.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b2.t0_4 ( read_p1_b2.nor_r0_8 A ) ( read_p1_b2.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b2.t2_4 ( read_p1_b2.aoi_r2_w0 Y ) ( read_p1_b2.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b2.t4_6 ( read_p1_b2.nand_r4_8 A ) ( read_p1_b2.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b2.t4_8 ( read_p1_b2.nor_r0_8 B ) ( read_p1_b2.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b2.t6_8 ( read_p1_b2.aoi_r2_w1 Y ) ( read_p1_b2.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b3.t0_2 ( read_p1_b3.nand_r0_4 A ) ( read_p1_b3.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b3.t0_4 ( read_p1_b3.nor_r0_8 A ) ( read_p1_b3.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b3.t2_4 ( read_p1_b3.aoi_r2_w0 Y ) ( read_p1_b3.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b3.t4_6 ( read_p1_b3.nand_r4_8 A ) ( read_p1_b3.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b3.t4_8 ( read_p1_b3.nor_r0_8 B ) ( read_p1_b3.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b3.t6_8 ( read_p1_b3.aoi_r2_w1 Y ) ( read_p1_b3.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b4.t0_2 ( read_p1_b4.nand_r0_4 A ) ( read_p1_b4.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b4.t0_4 ( read_p1_b4.nor_r0_8 A ) ( read_p1_b4.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b4.t2_4 ( read_p1_b4.aoi_r2_w0 Y ) ( read_p1_b4.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b4.t4_6 ( read_p1_b4.nand_r4_8 A ) ( read_p1_b4.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b4.t4_8 ( read_p1_b4.nor_r0_8 B ) ( read_p1_b4.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b4.t6_8 ( read_p1_b4.aoi_r2_w1 Y ) ( read_p1_b4.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b5.t0_2 ( read_p1_b5.nand_r0_4 A ) ( read_p1_b5.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b5.t0_4 ( read_p1_b5.nor_r0_8 A ) ( read_p1_b5.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b5.t2_4 ( read_p1_b5.aoi_r2_w0 Y ) ( read_p1_b5.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b5.t4_6 ( read_p1_b5.nand_r4_8 A ) ( read_p1_b5.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b5.t4_8 ( read_p1_b5.nor_r0_8 B ) ( read_p1_b5.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b5.t6_8 ( read_p1_b5.aoi_r2_w1 Y ) ( read_p1_b5.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b6.t0_2 ( read_p1_b6.nand_r0_4 A ) ( read_p1_b6.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b6.t0_4 ( read_p1_b6.nor_r0_8 A ) ( read_p1_b6.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b6.t2_4 ( read_p1_b6.aoi_r2_w0 Y ) ( read_p1_b6.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b6.t4_6 ( read_p1_b6.nand_r4_8 A ) ( read_p1_b6.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b6.t4_8 ( read_p1_b6.nor_r0_8 B ) ( read_p1_b6.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b6.t6_8 ( read_p1_b6.aoi_r2_w1 Y ) ( read_p1_b6.nand_r4_8 B ) + USE SIGNAL ; ++ - read_p1_b7.t0_2 ( read_p1_b7.nand_r0_4 A ) ( read_p1_b7.aoi_r0_w0 Y ) + USE SIGNAL ; ++ - read_p1_b7.t0_4 ( read_p1_b7.nor_r0_8 A ) ( read_p1_b7.nand_r0_4 Y ) + USE SIGNAL ; ++ - read_p1_b7.t2_4 ( read_p1_b7.aoi_r2_w0 Y ) ( read_p1_b7.nand_r0_4 B ) + USE SIGNAL ; ++ - read_p1_b7.t4_6 ( read_p1_b7.nand_r4_8 A ) ( read_p1_b7.aoi_r0_w1 Y ) + USE SIGNAL ; ++ - read_p1_b7.t4_8 ( read_p1_b7.nor_r0_8 B ) ( read_p1_b7.nand_r4_8 Y ) + USE SIGNAL ; ++ - read_p1_b7.t6_8 ( read_p1_b7.aoi_r2_w1 Y ) ( read_p1_b7.nand_r4_8 B ) + USE SIGNAL ; ++ - storage_0_1_0.bit0.storage ( read_p1_b0.aoi_r0_w1 A2 ) ( read_p0_b0.aoi_r0_w1 A2 ) ( storage_0_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit1.storage ( read_p1_b1.aoi_r0_w1 A2 ) ( read_p0_b1.aoi_r0_w1 A2 ) ( storage_0_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit2.storage ( read_p1_b2.aoi_r0_w1 A2 ) ( read_p0_b2.aoi_r0_w1 A2 ) ( storage_0_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit3.storage ( read_p1_b3.aoi_r0_w1 A2 ) ( read_p0_b3.aoi_r0_w1 A2 ) ( storage_0_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit4.storage ( read_p1_b4.aoi_r0_w1 A2 ) ( read_p0_b4.aoi_r0_w1 A2 ) ( storage_0_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit5.storage ( read_p1_b5.aoi_r0_w1 A2 ) ( read_p0_b5.aoi_r0_w1 A2 ) ( storage_0_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit6.storage ( read_p1_b6.aoi_r0_w1 A2 ) ( read_p0_b6.aoi_r0_w1 A2 ) ( storage_0_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.bit7.storage ( read_p1_b7.aoi_r0_w1 A2 ) ( read_p0_b7.aoi_r0_w1 A2 ) ( storage_0_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_0_1_0.gclock ( storage_0_1_0.cg GCLK ) ( storage_0_1_0.bit7.bit CLK ) ( storage_0_1_0.bit6.bit CLK ) ( storage_0_1_0.bit5.bit CLK ) ( storage_0_1_0.bit4.bit CLK ) ( storage_0_1_0.bit3.bit CLK ) ( storage_0_1_0.bit2.bit CLK ) ++ ( storage_0_1_0.bit1.bit CLK ) ( storage_0_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_0_1_0.we ( storage_0_1_0.gcand Y ) ( storage_0_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_0_0.bit0.storage ( storage_1_0_0.bit0.bit QN ) ( read_p1_b0.aoi_r0_w0 B2 ) ( read_p0_b0.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit1.storage ( storage_1_0_0.bit1.bit QN ) ( read_p1_b1.aoi_r0_w0 B2 ) ( read_p0_b1.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit2.storage ( storage_1_0_0.bit2.bit QN ) ( read_p1_b2.aoi_r0_w0 B2 ) ( read_p0_b2.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit3.storage ( storage_1_0_0.bit3.bit QN ) ( read_p1_b3.aoi_r0_w0 B2 ) ( read_p0_b3.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit4.storage ( storage_1_0_0.bit4.bit QN ) ( read_p1_b4.aoi_r0_w0 B2 ) ( read_p0_b4.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit5.storage ( storage_1_0_0.bit5.bit QN ) ( read_p1_b5.aoi_r0_w0 B2 ) ( read_p0_b5.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit6.storage ( storage_1_0_0.bit6.bit QN ) ( read_p1_b6.aoi_r0_w0 B2 ) ( read_p0_b6.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.bit7.storage ( storage_1_0_0.bit7.bit QN ) ( read_p1_b7.aoi_r0_w0 B2 ) ( read_p0_b7.aoi_r0_w0 B2 ) + USE SIGNAL ; ++ - storage_1_0_0.gclock ( storage_1_0_0.cg GCLK ) ( storage_1_0_0.bit7.bit CLK ) ( storage_1_0_0.bit6.bit CLK ) ( storage_1_0_0.bit5.bit CLK ) ( storage_1_0_0.bit4.bit CLK ) ( storage_1_0_0.bit3.bit CLK ) ( storage_1_0_0.bit2.bit CLK ) ++ ( storage_1_0_0.bit1.bit CLK ) ( storage_1_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_0_0.we ( storage_1_0_0.gcand Y ) ( storage_1_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_1_1_0.bit0.storage ( storage_1_1_0.bit0.bit QN ) ( read_p1_b0.aoi_r0_w1 B2 ) ( read_p0_b0.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit1.storage ( storage_1_1_0.bit1.bit QN ) ( read_p1_b1.aoi_r0_w1 B2 ) ( read_p0_b1.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit2.storage ( storage_1_1_0.bit2.bit QN ) ( read_p1_b2.aoi_r0_w1 B2 ) ( read_p0_b2.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit3.storage ( storage_1_1_0.bit3.bit QN ) ( read_p1_b3.aoi_r0_w1 B2 ) ( read_p0_b3.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit4.storage ( storage_1_1_0.bit4.bit QN ) ( read_p1_b4.aoi_r0_w1 B2 ) ( read_p0_b4.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit5.storage ( storage_1_1_0.bit5.bit QN ) ( read_p1_b5.aoi_r0_w1 B2 ) ( read_p0_b5.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit6.storage ( storage_1_1_0.bit6.bit QN ) ( read_p1_b6.aoi_r0_w1 B2 ) ( read_p0_b6.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.bit7.storage ( storage_1_1_0.bit7.bit QN ) ( read_p1_b7.aoi_r0_w1 B2 ) ( read_p0_b7.aoi_r0_w1 B2 ) + USE SIGNAL ; ++ - storage_1_1_0.gclock ( storage_1_1_0.cg GCLK ) ( storage_1_1_0.bit7.bit CLK ) ( storage_1_1_0.bit6.bit CLK ) ( storage_1_1_0.bit5.bit CLK ) ( storage_1_1_0.bit4.bit CLK ) ( storage_1_1_0.bit3.bit CLK ) ( storage_1_1_0.bit2.bit CLK ) ++ ( storage_1_1_0.bit1.bit CLK ) ( storage_1_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_1_1_0.we ( storage_1_1_0.gcand Y ) ( storage_1_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_0_0.bit0.storage ( read_p1_b0.aoi_r2_w0 A2 ) ( read_p0_b0.aoi_r2_w0 A2 ) ( storage_2_0_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit1.storage ( read_p1_b1.aoi_r2_w0 A2 ) ( read_p0_b1.aoi_r2_w0 A2 ) ( storage_2_0_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit2.storage ( read_p1_b2.aoi_r2_w0 A2 ) ( read_p0_b2.aoi_r2_w0 A2 ) ( storage_2_0_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit3.storage ( read_p1_b3.aoi_r2_w0 A2 ) ( read_p0_b3.aoi_r2_w0 A2 ) ( storage_2_0_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit4.storage ( read_p1_b4.aoi_r2_w0 A2 ) ( read_p0_b4.aoi_r2_w0 A2 ) ( storage_2_0_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit5.storage ( read_p1_b5.aoi_r2_w0 A2 ) ( read_p0_b5.aoi_r2_w0 A2 ) ( storage_2_0_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit6.storage ( read_p1_b6.aoi_r2_w0 A2 ) ( read_p0_b6.aoi_r2_w0 A2 ) ( storage_2_0_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.bit7.storage ( read_p1_b7.aoi_r2_w0 A2 ) ( read_p0_b7.aoi_r2_w0 A2 ) ( storage_2_0_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_0_0.gclock ( storage_2_0_0.cg GCLK ) ( storage_2_0_0.bit7.bit CLK ) ( storage_2_0_0.bit6.bit CLK ) ( storage_2_0_0.bit5.bit CLK ) ( storage_2_0_0.bit4.bit CLK ) ( storage_2_0_0.bit3.bit CLK ) ( storage_2_0_0.bit2.bit CLK ) ++ ( storage_2_0_0.bit1.bit CLK ) ( storage_2_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_0_0.we ( storage_2_0_0.gcand Y ) ( storage_2_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_2_1_0.bit0.storage ( read_p1_b0.aoi_r2_w1 A2 ) ( read_p0_b0.aoi_r2_w1 A2 ) ( storage_2_1_0.bit0.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit1.storage ( read_p1_b1.aoi_r2_w1 A2 ) ( read_p0_b1.aoi_r2_w1 A2 ) ( storage_2_1_0.bit1.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit2.storage ( read_p1_b2.aoi_r2_w1 A2 ) ( read_p0_b2.aoi_r2_w1 A2 ) ( storage_2_1_0.bit2.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit3.storage ( read_p1_b3.aoi_r2_w1 A2 ) ( read_p0_b3.aoi_r2_w1 A2 ) ( storage_2_1_0.bit3.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit4.storage ( read_p1_b4.aoi_r2_w1 A2 ) ( read_p0_b4.aoi_r2_w1 A2 ) ( storage_2_1_0.bit4.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit5.storage ( read_p1_b5.aoi_r2_w1 A2 ) ( read_p0_b5.aoi_r2_w1 A2 ) ( storage_2_1_0.bit5.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit6.storage ( read_p1_b6.aoi_r2_w1 A2 ) ( read_p0_b6.aoi_r2_w1 A2 ) ( storage_2_1_0.bit6.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.bit7.storage ( read_p1_b7.aoi_r2_w1 A2 ) ( read_p0_b7.aoi_r2_w1 A2 ) ( storage_2_1_0.bit7.bit QN ) + USE SIGNAL ; ++ - storage_2_1_0.gclock ( storage_2_1_0.cg GCLK ) ( storage_2_1_0.bit7.bit CLK ) ( storage_2_1_0.bit6.bit CLK ) ( storage_2_1_0.bit5.bit CLK ) ( storage_2_1_0.bit4.bit CLK ) ( storage_2_1_0.bit3.bit CLK ) ( storage_2_1_0.bit2.bit CLK ) ++ ( storage_2_1_0.bit1.bit CLK ) ( storage_2_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_2_1_0.we ( storage_2_1_0.gcand Y ) ( storage_2_1_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_0_0.bit0.storage ( storage_3_0_0.bit0.bit QN ) ( read_p1_b0.aoi_r2_w0 B2 ) ( read_p0_b0.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit1.storage ( storage_3_0_0.bit1.bit QN ) ( read_p1_b1.aoi_r2_w0 B2 ) ( read_p0_b1.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit2.storage ( storage_3_0_0.bit2.bit QN ) ( read_p1_b2.aoi_r2_w0 B2 ) ( read_p0_b2.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit3.storage ( storage_3_0_0.bit3.bit QN ) ( read_p1_b3.aoi_r2_w0 B2 ) ( read_p0_b3.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit4.storage ( storage_3_0_0.bit4.bit QN ) ( read_p1_b4.aoi_r2_w0 B2 ) ( read_p0_b4.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit5.storage ( storage_3_0_0.bit5.bit QN ) ( read_p1_b5.aoi_r2_w0 B2 ) ( read_p0_b5.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit6.storage ( storage_3_0_0.bit6.bit QN ) ( read_p1_b6.aoi_r2_w0 B2 ) ( read_p0_b6.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.bit7.storage ( storage_3_0_0.bit7.bit QN ) ( read_p1_b7.aoi_r2_w0 B2 ) ( read_p0_b7.aoi_r2_w0 B2 ) + USE SIGNAL ; ++ - storage_3_0_0.gclock ( storage_3_0_0.cg GCLK ) ( storage_3_0_0.bit7.bit CLK ) ( storage_3_0_0.bit6.bit CLK ) ( storage_3_0_0.bit5.bit CLK ) ( storage_3_0_0.bit4.bit CLK ) ( storage_3_0_0.bit3.bit CLK ) ( storage_3_0_0.bit2.bit CLK ) ++ ( storage_3_0_0.bit1.bit CLK ) ( storage_3_0_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_0_0.we ( storage_3_0_0.gcand Y ) ( storage_3_0_0.cg ENA ) + USE SIGNAL ; ++ - storage_3_1_0.bit0.storage ( storage_3_1_0.bit0.bit QN ) ( read_p1_b0.aoi_r2_w1 B2 ) ( read_p0_b0.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit1.storage ( storage_3_1_0.bit1.bit QN ) ( read_p1_b1.aoi_r2_w1 B2 ) ( read_p0_b1.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit2.storage ( storage_3_1_0.bit2.bit QN ) ( read_p1_b2.aoi_r2_w1 B2 ) ( read_p0_b2.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit3.storage ( storage_3_1_0.bit3.bit QN ) ( read_p1_b3.aoi_r2_w1 B2 ) ( read_p0_b3.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit4.storage ( storage_3_1_0.bit4.bit QN ) ( read_p1_b4.aoi_r2_w1 B2 ) ( read_p0_b4.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit5.storage ( storage_3_1_0.bit5.bit QN ) ( read_p1_b5.aoi_r2_w1 B2 ) ( read_p0_b5.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit6.storage ( storage_3_1_0.bit6.bit QN ) ( read_p1_b6.aoi_r2_w1 B2 ) ( read_p0_b6.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.bit7.storage ( storage_3_1_0.bit7.bit QN ) ( read_p1_b7.aoi_r2_w1 B2 ) ( read_p0_b7.aoi_r2_w1 B2 ) + USE SIGNAL ; ++ - storage_3_1_0.gclock ( storage_3_1_0.cg GCLK ) ( storage_3_1_0.bit7.bit CLK ) ( storage_3_1_0.bit6.bit CLK ) ( storage_3_1_0.bit5.bit CLK ) ( storage_3_1_0.bit4.bit CLK ) ( storage_3_1_0.bit3.bit CLK ) ( storage_3_1_0.bit2.bit CLK ) ++ ( storage_3_1_0.bit1.bit CLK ) ( storage_3_1_0.bit0.bit CLK ) + USE SIGNAL ; ++ - storage_3_1_0.we ( storage_3_1_0.gcand Y ) ( storage_3_1_0.cg ENA ) + USE SIGNAL ; ++ - w_sel_p0.select_w0 ( sel_buf_w_p0.sel_buf_0 Y ) + USE SIGNAL ; ++ - w_sel_p0.select_w1 ( sel_buf_w_p0.sel_buf_1 Y ) ( storage_0_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w2 ( sel_buf_w_p0.sel_buf_2 Y ) ( storage_1_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w3 ( sel_buf_w_p0.sel_buf_3 Y ) ( storage_1_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w4 ( sel_buf_w_p0.sel_buf_4 Y ) ( storage_2_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w5 ( sel_buf_w_p0.sel_buf_5 Y ) ( storage_2_1_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w6 ( sel_buf_w_p0.sel_buf_6 Y ) ( storage_3_0_0.gcand A ) + USE SIGNAL ; ++ - w_sel_p0.select_w7 ( sel_buf_w_p0.sel_buf_7 Y ) ( storage_3_1_0.gcand A ) + USE SIGNAL ; ++ - we[0] ( PIN we[0] ) ( storage_3_1_0.gcand B ) ( storage_3_0_0.gcand B ) ( storage_2_1_0.gcand B ) ( storage_2_0_0.gcand B ) ( storage_1_1_0.gcand B ) ( storage_1_0_0.gcand B ) ++ ( storage_0_1_0.gcand B ) + USE SIGNAL ; ++END NETS ++END DESIGN +diff --git a/src/ram/test/make_8x8_2r1w_contiguous_asap7.tcl b/src/ram/test/make_8x8_2r1w_contiguous_asap7.tcl +new file mode 100644 +index 0000000000..338042fe21 +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_contiguous_asap7.tcl +@@ -0,0 +1,37 @@ ++# generate_ram on asap7: 4 interleaved banks, 2 side by side, each word's ++# bits contiguous in its row (-bank_column_layout contiguous), so its ++# selects span its own bits. ++source "helpers.tcl" ++ ++read_liberty ../../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz ++read_liberty ../../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib ++read_liberty ../../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz ++ ++read_lef ../../../test/asap7/asap7_tech_1x_201209.lef ++read_lef ../../../test/asap7/asap7sc7p5t_28_R_1x_220121a.lef ++ ++set behavioral_file [make_result_file make_8x8_2r1w_contiguous_asap7_behavioral.v] ++ ++generate_ram_netlist \ ++ -mask_size 8 \ ++ -word_size 8 \ ++ -num_words 8 \ ++ -r_ports 2 \ ++ -w_ports 1 \ ++ -storage_cell DFFHQNx1_ASAP7_75t_R \ ++ -banks 4 \ ++ -bank_columns 2 \ ++ -bank_order interleaved \ ++ -bank_column_layout contiguous \ ++ -zero_word 0 \ ++ -write_behavioral_verilog $behavioral_file ++ ++set def_file [make_result_file make_8x8_2r1w_contiguous_asap7.def] ++write_def $def_file ++diff_files make_8x8_2r1w_contiguous_asap7.defok $def_file ++ ++diff_files make_8x8_2r1w_contiguous_asap7_behavioral.vok $behavioral_file ++ ++puts "pass" +diff --git a/src/ram/test/make_8x8_2r1w_contiguous_asap7_behavioral.vok b/src/ram/test/make_8x8_2r1w_contiguous_asap7_behavioral.vok +new file mode 100644 +index 0000000000..373f465efb +--- /dev/null ++++ b/src/ram/test/make_8x8_2r1w_contiguous_asap7_behavioral.vok +@@ -0,0 +1,42 @@ ++module RAM8x8 ( ++ clk, ++ D, ++ Q0, ++ Q1, ++ addr_w, ++ addr_r0, ++ addr_r1, ++ we ++); ++ input clk; ++ input [7:0] D; ++ output reg [7:0] Q0; ++ output reg [7:0] Q1; ++ input [2:0] addr_w; ++ input [2:0] addr_r0; ++ input [2:0] addr_r1; ++ input [0:0] we; ++ ++ // memory array declaration ++ reg [7:0] mem[0:7]; ++ ++ // write logic ++ integer i; ++ always @(posedge clk) begin ++ for (i = 0; i < 1; i = i + 1) begin ++ if (we[i] && addr_w != 0) begin ++ mem[addr_w][i*8 +:8] <= D[i*8 +:8]; ++ end ++ end ++ end ++ ++ // read logic ++ always @(*) begin ++ Q0 = addr_r0 == 0 ? 8'd0 : mem[addr_r0]; ++ end ++ ++ always @(*) begin ++ Q1 = addr_r1 == 0 ? 8'd0 : mem[addr_r1]; ++ end ++ ++endmodule +diff --git a/src/ram/test/regression_tests.tcl b/src/ram/test/regression_tests.tcl +index 0dc0ecc2c4..0a661e137d 100644 +--- a/src/ram/test/regression_tests.tcl ++++ b/src/ram/test/regression_tests.tcl +@@ -15,6 +15,7 @@ record_tests { + make_8x8_2r1w_mux_asap7 + make_8x8_2r2w_or_asap7 + make_8x8_2r1w_service_asap7 ++ make_8x8_2r1w_contiguous_asap7 + make_8x8_2r1w_unplaced_asap7 + make_8x8_latch_sky130 + } diff --git a/patches/0109-orfs-regfiles-generate-ram.patch b/patches/0109-orfs-regfiles-generate-ram.patch index 800ed98b1..8ee7d5fef 100644 --- a/patches/0109-orfs-regfiles-generate-ram.patch +++ b/patches/0109-orfs-regfiles-generate-ram.patch @@ -58,7 +58,7 @@ diff --git a/flow/scripts/memories/regfile_ram.py b/flow/scripts/memories/regfil new file mode 100644 --- /dev/null +++ b/flow/scripts/memories/regfile_ram.py -@@ -0,0 +1,597 @@ +@@ -0,0 +1,690 @@ +"""AUTO_MEMORIES_REGFILES through OpenROAD's generate_ram. + +A register-file spec (the keys generate_regfile reads) is translated to @@ -81,7 +81,10 @@ new file mode 100644 +periphery as a Verilog module, _ram, around the core, +_ram_core, which is then what is inlined or the macro. A macro +kept to the end (mode macro) gets its pins from OpenROAD's pin placer on -+the spec's pin layers and its liberty from write_timing_model. ++the spec's pin layers, its liberty from write_timing_model and its ++power from rails on its rows and straps with the VDD and VSS pins ++(power_rails, power_layer, power_width, power_pitch, power_offset; ++asap7's by default). +""" + +from __future__ import annotations @@ -93,6 +96,9 @@ new file mode 100644 +import subprocess +from pathlib import Path + ++# the longest a word's bits may run in a row before it is folded, um ++WORD_SPAN_UM = 150 ++ +# keys generate_ram has no counterpart for yet +UNSUPPORTED = {"pin_track", "lib"} + @@ -164,7 +170,7 @@ new file mode 100644 + "-name", + block, + "-mask_size", -+ str(bits // folds), ++ str(-(-bits // folds)), + "-word_size", + str(bits), + "-num_words", @@ -179,6 +185,18 @@ new file mode 100644 + "-decoder", + "word", + ] ++ if len(_values(lines, "write")) > 1: ++ # two ports writing one word in a cycle: generate_regfile's ++ # default ORs their data, as firtool's register files do ++ args += ["-write_priority", _one(lines, "write_priority", "or")] ++ if int(_one(lines, "bank_columns", "1")) > 1 and not _values( ++ lines, "bank_column_layout" ++ ): ++ # a row's words each contiguous, as generate_regfile's tile per ++ # word: interleaved, a word's selects and write enables run the ++ # whole row (XiangShan's RobEntryFile: 6,483 slew violations in a ++ # parent, against 608) ++ args += ["-bank_column_layout", "contiguous"] + if storage: + args += ["-storage_cell", storage] + if folds > 1: @@ -186,7 +204,14 @@ new file mode 100644 + args += ["-bit_folds", str(folds)] + if _values(lines, "read_banked"): + args += ["-rb_ports", str(len(_values(lines, "read_banked")))] -+ for key in ("zero_word", "banks", "bank_columns", "bank_order", "read_latency"): ++ for key in ( ++ "zero_word", ++ "banks", ++ "bank_columns", ++ "bank_order", ++ "bank_column_layout", ++ "read_latency", ++ ): + if _values(lines, key): + args += [f"-{key}", _one(lines, key)] + if async_reset: @@ -202,6 +227,13 @@ new file mode 100644 + ] + if roles: + args += ["-cells", "{" + " ".join(roles) + "}"] ++ # generate_regfile's service columns: `service_sites` empty sites after ++ # every `tap_columns` storage columns, room for a parent's buffers in ++ # the array; 40 by default in a macro kept to the end, else none ++ sites = int(_one(lines, "service_sites", "40" if shape == "macro" else "0")) ++ if sites > 0: ++ every = _one(lines, "tap_columns", "8") ++ args += ["-service_columns", f"{{{every} {sites}}}"] + if _one(lines, "periphery") == "verilog": + args += ["-periphery", "verilog", "-pin_layer", _one(lines, "pin_layer", "M4")] + elif shape == "netlist": @@ -554,18 +586,41 @@ new file mode 100644 + return float(width), float(height) + + width, height = build(lines) -+ # generate_regfile chose its rows per word itself: where the spec names -+ # no folds and a word in one row came out more than 8 times as wide as -+ # tall (XiangShan's IntRegFile, 12 reads and 9 writes, 48), fold it -+ # into the power of two of rows nearest the square. A heuristic: a -+ # strip of a few to one can be the shape that fits (riscv32i's, 6, sits -+ # under its FakeRAMs), so a spec names bit_folds to choose. ++ # generate_regfile chose its rows per word itself; where the spec names ++ # no folds, fold a word into a power of two of rows while ++ # ++ # - the array is more than 8 times as wide as tall, toward the square ++ # (XiangShan's IntRegFile, 12 reads and 9 writes, 48 to one); a strip ++ # of a few to one can be the shape that fits (riscv32i's, 6, sits ++ # under its FakeRAMs), so that alone does not fold; ++ # - or one word's bits span more than WORD_SPAN_UM: its selects and ++ # write enables, driven from one cell, are that long, and a parent ++ # buffers them inside the full array, where nothing legalizes ++ # (XiangShan's RenameBufferFile, a word a row 258 um wide, failed; ++ # RobEntryFile at 74 um and IntRegFile at 96 um a word did not). ++ # ++ # A spec names bit_folds to choose. + bits = int(_one(lines, "bits")) -+ if not _values(lines, "bit_folds") and width > 8 * height: ++ dbu = float(outline.read_text().split()[2]) ++ # the words side by side in a row, each contiguous (see _args) unless ++ # the spec interleaves them, when a word spans the row ++ row_words = ( ++ int(_one(lines, "bank_columns", "1")) ++ if _one(lines, "bank_column_layout", "contiguous") == "contiguous" ++ else 1 ++ ) ++ span_um = width / dbu / row_words ++ if not _values(lines, "bit_folds"): + folds = 1 -+ while folds * 2 <= bits and bits % (folds * 2) == 0 and ( -+ folds * 2 -+ ) ** 2 <= 2 * width / height: ++ # a short last fold is allowed, an empty one is not ++ while ( ++ folds * 2 <= bits ++ and (folds * 2 - 1) * -(-bits // (folds * 2)) < bits ++ and ( ++ (width > 8 * height and (folds * 2) ** 2 <= 2 * width / height) ++ or span_um / folds > WORD_SPAN_UM ++ ) ++ ): + folds *= 2 + if folds > 1: + lines = lines + [["bit_folds", str(folds)]] @@ -607,6 +662,44 @@ new file mode 100644 + f"make_tracks {layer} -x_offset $o -x_pitch $p" + " -y_offset $o -y_pitch $p\n" + ) ++ # its power, as a hardened block's: rails on the rows, straps ++ # with the VDD and VSS pins the parent's grid connects to ++ # (asap7's BLOCK_grid_strategy.tcl, without its ring) ++ rails = (_values(lines, "power_rails") or [["M1", "M2"]])[-1] ++ rail_w = _one(lines, "power_rail_width", "0.018") ++ strap = _one(lines, "power_layer", "M5") ++ strap_w = _one(lines, "power_width", "0.12") ++ pitch = _one(lines, "power_pitch", "2.976") ++ offset = _one(lines, "power_offset", "1.5") ++ tcl += ( ++ "set block [ord::get_db_block]\n" ++ "foreach {name type} {VDD POWER VSS GROUND} {\n" ++ " set net [$block findNet $name]\n" ++ ' if {$net eq "NULL"} { set net [odb::dbNet_create $block $name] }\n' ++ " $net setSpecial\n" ++ " $net setSigType $type\n" ++ "}\n" ++ "add_global_connection -net VDD -inst_pattern {.*}" ++ " -pin_pattern {^VDD$} -power\n" ++ "add_global_connection -net VSS -inst_pattern {.*}" ++ " -pin_pattern {^VSS$} -ground\n" ++ "global_connect\n" ++ "set_voltage_domain -name CORE -power VDD -ground VSS\n" ++ f"define_pdn_grid -name block -voltage_domains CORE -pins {strap}\n" ++ ) ++ for rail in rails: ++ tcl += ( ++ f"add_pdn_stripe -grid block -layer {rail} -width {rail_w}" ++ " -followpins\n" ++ ) ++ tcl += ( ++ f"add_pdn_stripe -grid block -layer {strap} -width {strap_w}" ++ f" -pitch {pitch} -offset {offset} -extend_to_boundary\n" ++ ) ++ for lo, hi in zip(rails + [strap], rails[1:] + [strap]): ++ if lo != hi: ++ tcl += f"add_pdn_connect -grid block -layers {{{lo} {hi}}}\n" ++ tcl += "pdngen\n" + tcl += f"place_pins -hor_layers {h} -ver_layers {v}\n" + tcl += _MACRO_TCL.format(out=out_dir, block=block) + if shape == "macro": diff --git a/private/rules.bzl b/private/rules.bzl index 441da3a0b..1e06ecbe3 100644 --- a/private/rules.bzl +++ b/private/rules.bzl @@ -2103,7 +2103,7 @@ def _yosys_impl(ctx): fail("AUTO_MEMORIES=1 but no FakeRAM run.py among the files of " + str(ctx.attr._fakeram.label) + " in " + str(ctx.label)) - # AUTO_MEMORIES_REGFILES: OpenROAD's generate_regfile builds each + # AUTO_MEMORIES_REGFILES: OpenROAD's generate_ram builds each # listed register file inside the memories step, so openroad is a # tool of the canonicalize action, named to make through # OPENROAD_EXE. The views land in results/memories beside the diff --git a/private/stages.bzl b/private/stages.bzl index e7186ccbb..7a72bceaa 100644 --- a/private/stages.bzl +++ b/private/stages.bzl @@ -189,7 +189,7 @@ def keep_modules(arguments): # one would build without the register files it asks for. RETIRED_ARGUMENTS = { "STRUCTURED_MEMORIES": "AUTO_MEMORIES_REGFILES lists the register-file " + - "specs, built by OpenROAD's generate_regfile", + "specs, built by OpenROAD's generate_ram", "STRUCTURED_PLACEMENT": "AUTO_MEMORIES_MACRO_PLACE lists the register " + "files placed as macros, which dissolve into " + "their cells after macro placement; place them " + diff --git a/test/coremark_joule/designs/asap7/xiangshan/BUILD b/test/coremark_joule/designs/asap7/xiangshan/BUILD index b8c01de7c..17b8ca297 100644 --- a/test/coremark_joule/designs/asap7/xiangshan/BUILD +++ b/test/coremark_joule/designs/asap7/xiangshan/BUILD @@ -54,7 +54,7 @@ exports_files( # The register-file specs: the parent's three placed netlists, at real # size in a parent of flops, are the battery's rung for what the resizer, # CTS and the router do to an array of this size (test/structured_netlist, -# scaffold.bzl); every spec is generate_regfile's golden case +# scaffold.bzl); every spec is generate_ram's golden case # (tools/structured_gen:golden_test). exports_files( glob(["*.regfile"]), diff --git a/test/coremark_joule/designs/asap7/xiangshan/plan/place_macros.tcl b/test/coremark_joule/designs/asap7/xiangshan/plan/place_macros.tcl index 5fc218131..dfd56960b 100644 --- a/test/coremark_joule/designs/asap7/xiangshan/plan/place_macros.tcl +++ b/test/coremark_joule/designs/asap7/xiangshan/plan/place_macros.tcl @@ -48,17 +48,22 @@ foreach {lo hi} { puts "place_macros.tcl: $bands soft placement blockage(s) over the blocks' bands; the rows stay" # The plan's register files (AUTO_MEMORIES_REGFILES in mode netlist) are # macros until the end of this step, each found by its instance and placed -# where the plan put it; they dissolve into their cells after it. +# where the plan put it; they dissolve into their cells after it. The +# macro is the instance itself, or generate_ram's RAM, ram, inside the +# wrapper that takes the module's place. foreach {inst x y} { core/backend/inner_ctrlBlock/rob/robEntryFile 20.944 1482.358 core/backend/inner_intRegion/intDataPath/intRegFile 350.128 1431.868 core/backend/inner_ctrlBlock/rob/rab/renameBuffer 766.928 1482.628 } { - set i [$block findInst $inst] + foreach name [list $inst $inst/ram $inst.ram] { + set i [$block findInst $name] + if { $i ne "NULL" } { break } + } if { $i eq "NULL" } { utl::error FLW 2 "plan: no register file instance $inst" } - place_macro -macro_name $inst -location [list $x $y] -orientation R0 -exact + place_macro -macro_name [$i getName] -location [list $x $y] -orientation R0 -exact $i setPlacementStatus FIRM puts "place_macros.tcl: register file $inst at $x $y um, R0" } diff --git a/test/planned_parent/leftover_macros.tcl b/test/planned_parent/leftover_macros.tcl index bc91d70d6..d72e16971 100644 --- a/test/planned_parent/leftover_macros.tcl +++ b/test/planned_parent/leftover_macros.tcl @@ -9,16 +9,39 @@ source $::env(SCRIPTS_DIR)/load.tcl load_design 2_floorplan.odb 2_floorplan.sdc set block [ord::get_db_block] # the core: every cell a netlist's .place file names, under its instance -# (NETLISTS: the plan's pairs) +# (NETLISTS: the plan's pairs). The block is +# generate_ram's _ram (its core _ram_core with the +# periphery as Verilog) inside the wrapper in the module's place, its +# cells under the wrapper's ram instance; or the module itself. set core [dict create] foreach {module path} $::env(NETLISTS) { - set place "$::env(RESULTS_DIR)/memories/$module.place" - if { ![file exists $place] } { error "leftover_macros.tcl: no $place for $path" } + set place "" + foreach name [list ${module}_ram_core ${module}_ram $module] { + if { [file exists "$::env(RESULTS_DIR)/memories/$name.place"] } { + set place "$::env(RESULTS_DIR)/memories/$name.place" + break + } + } + if { $place eq "" } { error "leftover_macros.tcl: no .place for $module ($path)" } + set names {} set f [open $place r] while { [gets $f pl] >= 0 } { - if { [lindex $pl 0] ne "" } { dict set core "$path/[lindex $pl 0]" 1 } + if { [lindex $pl 0] ne "" } { lappend names [lindex $pl 0] } } close $f + # the prefix: try names until one is there (a cell the parent never + # reads is gone as dead logic) + set prefix "$path/" + foreach name $names { + foreach candidate [list "$path/" "$path.ram/" "$path/ram/"] { + if { [$block findInst "$candidate$name"] ne "NULL" } { + set prefix $candidate + break + } + } + if { [$block findInst "$prefix$name"] ne "NULL" } { break } + } + foreach name $names { dict set core "$prefix$name" 1 } } set macros {} array set box {} @@ -33,7 +56,8 @@ foreach inst [$block getInsts] { } continue } - set key [file dirname [$inst getName]] + # a netlist by its instance, the wrapper's ram folded into it + regsub {[./]ram$} [file dirname [$inst getName]] "" key if { ![string match u_file* $key] } { continue } if { ![info exists cells($key)] } { set loose($key) 0 diff --git a/test/planned_parent/plan/place_macros.tcl b/test/planned_parent/plan/place_macros.tcl index 6bdb60ac6..336ebe6b2 100644 --- a/test/planned_parent/plan/place_macros.tcl +++ b/test/planned_parent/plan/place_macros.tcl @@ -47,17 +47,22 @@ foreach {lo hi} { puts "place_macros.tcl: $bands soft placement blockage(s) over the blocks' bands; the rows stay" # The plan's register files (AUTO_MEMORIES_REGFILES in mode netlist) are # macros until the end of this step, each found by its instance and placed -# where the plan put it; they dissolve into their cells after it. +# where the plan put it; they dissolve into their cells after it. The +# macro is the instance itself, or generate_ram's RAM, ram, inside the +# wrapper that takes the module's place. foreach {inst x y} { u_filea 20.944 148.717 u_fileb 61.744 148.717 u_filec 20.944 107.400 } { - set i [$block findInst $inst] + foreach name [list $inst $inst/ram $inst.ram] { + set i [$block findInst $name] + if { $i ne "NULL" } { break } + } if { $i eq "NULL" } { utl::error FLW 2 "plan: no register file instance $inst" } - place_macro -macro_name $inst -location [list $x $y] -orientation R0 -exact + place_macro -macro_name [$i getName] -location [list $x $y] -orientation R0 -exact $i setPlacementStatus FIRM puts "place_macros.tcl: register file $inst at $x $y um, R0" } diff --git a/test/regfile/BUILD.bazel b/test/regfile/BUILD.bazel index 10eeffda0..502c63d2f 100644 --- a/test/regfile/BUILD.bazel +++ b/test/regfile/BUILD.bazel @@ -162,29 +162,25 @@ build_test( targets = [":regfile_top_keep_blackboxes"], ) -# OpenROAD's own ram tests, generate_ram's and generate_regfile's (patch -# 0010), so a change to the generator runs them here: CI tests this +# OpenROAD's own ram tests, generate_ram's and those patches 0011 to 0023 +# add, so a change to the generator runs them here: CI tests this # repository's packages, not @openroad's. test_suite( name = "openroad_ram_tests", tests = [ - "@openroad//src/ram/test:generate_regfile_asap7-tcl_test", - "@openroad//src/ram/test:generate_regfile_clock_gate_asap7-tcl_test", - "@openroad//src/ram/test:generate_regfile_modes_asap7-tcl_test", - "@openroad//src/ram/test:generate_regfile_reset_asap7-tcl_test", - "@openroad//src/ram/test:generate_regfile_reset_high_asap7-tcl_test", - "@openroad//src/ram/test:generate_regfile_sv_ports_asap7-tcl_test", - "@openroad//src/ram/test:generate_regfile_write_priority_asap7-tcl_test", "@openroad//src/ram/test:make_7x7_1r2w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_2r1w_nangate45-tcl_test", "@openroad//src/ram/test:make_7x7_nangate45-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_and_or_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_banks_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_contiguous_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_mux_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_reset_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_2r1w_service_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_sky130-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_unplaced_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_2r1w_zero_asap7-tcl_test", + "@openroad//src/ram/test:make_8x8_2r2w_or_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_rb_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_rb_latency_asap7-tcl_test", "@openroad//src/ram/test:make_8x8_sky130-tcl_test", diff --git a/test/regfile/RegFile.regfile b/test/regfile/RegFile.regfile index b5f7ea063..7763e20f3 100644 --- a/test/regfile/RegFile.regfile +++ b/test/regfile/RegFile.regfile @@ -1,4 +1,4 @@ -# RegFile as a register file of placed standard cells (generate_regfile). +# RegFile as a register file of placed standard cells (generate_ram). # mode netlist: a macro through synthesis and macro placement, then its # cells, the core FIRM where the macro was placed, the address decode # left to placement. diff --git a/test/regfile/cores/BUILD.bazel b/test/regfile/cores/BUILD.bazel index 28c7b26c9..4db731291 100644 --- a/test/regfile/cores/BUILD.bazel +++ b/test/regfile/cores/BUILD.bazel @@ -1,10 +1,14 @@ -# generate_regfile's spec keys a small fixture does not reach, each -# simulated against the RTL it replaces (sim.bzl), every read compared -# under random reads, writes and resets. Seconds each. +# Register files of real designs through generate_ram (OpenROAD patches +# 0011 to 0023), by ORFS's own translation of their specs (regfile_ram.py, +# ORFS patch 0109), each simulated against the RTL it replaces (sim.bzl), +# every read compared under random reads, writes and resets. Seconds +# each. # -# - ibex's register file: `async_reset` (every word reset to zero), the -# port check reading a SystemVerilog header with a parameter list, and -# `unused` inputs; with a negative control, the reset dropped. +# - riscv32i's register file, in each write style and with its periphery +# as Verilog. +# - ibex's register file: `async_reset` (every word reset to zero), its +# SystemVerilog header, and `unused` inputs; with a negative control, +# the reset dropped. # - rf_wp: `write_priority last`, two writes to one word in one cycle, # the later port winning; with a negative control whose RTL lets the # earlier port win. @@ -24,6 +28,10 @@ py_binary( name = "ram_gen", srcs = ["ram_gen.py"], main = "ram_gen.py", + visibility = [ + "//test/structured_gen_lec:__pkg__", + "//tools/structured_gen:__pkg__", + ], ) stdcell_verilog( @@ -81,49 +89,26 @@ regfile_sim_test( spec = ":rf_wp.regfile", ) -# The same four through generate_ram (OpenROAD patches 0011 to 0023), by -# ORFS's own translation of the spec (regfile_ram.py, patch 0109): the -# wrapper in the RTL module's place, the reset's polarity adapted there, -# the unused inputs, the write priority; the negative controls show the -# harness sees generate_ram's netlist too. +# riscv32i's register file (test/regfile/riscv32i's specs): a hold mux +# per bit, a clock gate per word, and the periphery as Verilog. [ regfile_sim_test( - name = name, - expect_mismatch = expect_mismatch, - generator = "generate_ram", - module = module, - rtl = rtl, - rtl_module = module, + name = "riscv32i_%s_sim_test" % shape, + module = "regfile", + rtl = ["@orfs//flow/designs/src/riscv32i:regfile.v"], + rtl_module = "regfile", spec = spec, ) - for name, module, spec, rtl, expect_mismatch in [ - ( - "ibex_ram_sim_test", - "ibex_register_file_ff", - ":ibex_register_file_ff.regfile", - ["@orfs//flow/designs/src/ibex_sv:ibex_register_file_ff.sv"], - False, - ), - ( - "ibex_no_reset_ram_sim_test", - "ibex_register_file_ff", - ":ibex_no_reset.regfile", - ["@orfs//flow/designs/src/ibex_sv:ibex_register_file_ff.sv"], - True, - ), - ( - "write_last_ram_sim_test", - "rf_wp", - ":rf_wp.regfile", - [":write_last.v"], - False, - ), - ( - "write_first_ram_sim_test", - "rf_wp", - ":rf_wp.regfile", - [":write_first.v"], - True, - ), + for shape, spec in [ + ("mux", ":riscv32i_mux.regfile"), + ("clock_gate", "//test/regfile/riscv32i:inlined.regfile"), + ("periphery_verilog", "//test/regfile/riscv32i:inlined_verilog.regfile"), ] ] + +genrule( + name = "riscv32i_mux_regfile", + srcs = ["//test/regfile/riscv32i:inlined.regfile"], + outs = ["riscv32i_mux.regfile"], + cmd = "sed 's/^write_style clock_gate$$/write_style mux/' $< > $@ && grep -q '^write_style mux$$' $@", +) diff --git a/test/regfile/cores/gen_tb.py b/test/regfile/cores/gen_tb.py index a98d08944..f4ac5a0ab 100644 --- a/test/regfile/cores/gen_tb.py +++ b/test/regfile/cores/gen_tb.py @@ -1,4 +1,4 @@ -"""A testbench for a generate_regfile spec: the generated netlist beside a reference. +"""A testbench for a register-file spec: the generated netlist beside a reference. The reference is the RTL module the spec replaces (--rtl-module) or, when there is none, a behavioural memory built from the spec: words x bits, combinational @@ -41,8 +41,11 @@ "service_sites", "lib", "flop_output", + "pin_layer", "pin_layer_h", "pin_layer_v", + "periphery", + "mode", "store_name", "unused", "write_priority", diff --git a/test/regfile/cores/ibex_register_file_ff.regfile b/test/regfile/cores/ibex_register_file_ff.regfile index 315f40b9b..dee1e839c 100644 --- a/test/regfile/cores/ibex_register_file_ff.regfile +++ b/test/regfile/cores/ibex_register_file_ff.regfile @@ -1,5 +1,5 @@ # ibex's register file (src/ibex_sv/ibex_register_file_ff.sv) as -# generate_regfile builds it, for simulation against that RTL: 32 x 32 +# generate_ram builds it, for simulation against that RTL: 32 x 32 # with x0 reading zero, two combinational reads, one write through a # clock gate per word, every word reset to zero asynchronously by # rst_ni. With ibex's default diff --git a/test/regfile/cores/ram_gen.py b/test/regfile/cores/ram_gen.py index 5aa469755..9f80527ff 100644 --- a/test/regfile/cores/ram_gen.py +++ b/test/regfile/cores/ram_gen.py @@ -2,7 +2,9 @@ The netlist AUTO_MEMORIES_REGFILES inlines for the spec (the wrapper in the RTL module's place around generate_ram's RAM), its module renamed -_gen, for regfile_sim_test to simulate beside the reference. +_gen, for regfile_sim_test to simulate beside the reference +(--suffix "" keeps the name, for an equivalence check). With --shape +netlist or macro, --out is a directory that keeps every view. """ import argparse @@ -22,11 +24,21 @@ def main() -> int: p.add_argument("--lef", action="append", default=[], type=Path) p.add_argument("--lib", action="append", default=[]) p.add_argument("--out", required=True, type=Path) + p.add_argument("--suffix", default="_gen") + p.add_argument( + "--shape", default="inline", choices=["inline", "netlist", "macro"] + ) args = p.parse_args() spec = importlib.util.spec_from_file_location("regfile_ram", args.regfile_ram) regfile_ram = importlib.util.module_from_spec(spec) spec.loader.exec_module(regfile_ram) os.environ["LIB_FILES"] = " ".join(args.lib) + if args.shape != "inline": + args.out.mkdir(parents=True, exist_ok=True) + regfile_ram.generate( + args.spec, args.module, args.shape, args.openroad, args.lef, args.out + ) + return 0 with tempfile.TemporaryDirectory(dir=args.out.parent) as work: out_dir = Path(work) / "memories" out_dir.mkdir() @@ -34,7 +46,9 @@ def main() -> int: args.spec, args.module, "inline", args.openroad, args.lef, out_dir ) text = (out_dir / f"{args.module}.v").read_text() - text = text.replace(f"module {args.module} (", f"module {args.module}_gen (", 1) + text = text.replace( + f"module {args.module} (", f"module {args.module}{args.suffix} (", 1 + ) args.out.write_text(text) return 0 diff --git a/test/regfile/cores/sim.bzl b/test/regfile/cores/sim.bzl index 87a74d150..b6d9656de 100644 --- a/test/regfile/cores/sim.bzl +++ b/test/regfile/cores/sim.bzl @@ -1,8 +1,8 @@ """regfile_sim_test: a spec's generated netlist simulated beside its reference. -generate_regfile, or generate_ram through ORFS's translation of the spec -(regfile_ram.py, the netlist AUTO_MEMORIES_REGFILES inlines), builds the -spec into a structural netlist of asap7 cells; gen_tb.py writes a testbench that drives it and the reference +generate_ram, through ORFS's translation of the spec (regfile_ram.py, +the netlist AUTO_MEMORIES_REGFILES inlines), builds the spec into a +structural netlist of asap7 cells; gen_tb.py writes a testbench that drives it and the reference (the RTL module the spec replaces, or a behavioural memory built from the spec when there is none) with the same random reads, writes and resets, and the test fails on the first differing read. @@ -31,9 +31,8 @@ def regfile_sim_test( rtl_module = None, ties = {}, expect_mismatch = False, - stdcells = ":asap7_stdcell", - generator = "generate_regfile"): - """Simulates generate_regfile's netlist for `spec` against a reference. + stdcells = ":asap7_stdcell"): + """Simulates generate_ram's netlist for `spec` against a reference. Args: name: the test. @@ -46,56 +45,24 @@ def regfile_sim_test( expect_mismatch: a negative control, a spec known to be wrong: the test passes only if some read differs. stdcells: the stdcell_verilog target. - generator: generate_regfile, or generate_ram through regfile_ram.py. """ - if generator == "generate_ram": - native.genrule( - name = name + "_gen_v", - srcs = [spec, _TECH_LEF, _CELL_LEF, _REGFILE_RAM] + _LIBS, - outs = [name + "_gen.v"], - cmd = " ".join([ - "grep -v '^[[:space:]]*memory[[:space:]]' $(location %s) > $(@D)/%s.regfile &&" % (spec, name), - "$(execpath :ram_gen)", - "--regfile-ram $(location %s)" % _REGFILE_RAM, - "--spec $(@D)/%s.regfile" % name, - "--module " + module, - "--openroad $(location @openroad//:openroad)", - "--lef $(location %s) --lef $(location %s)" % (_TECH_LEF, _CELL_LEF), - ] + ["--lib $(location %s)" % lib for lib in _LIBS] + [ - "--out $@", - ]), - tools = ["@openroad", ":ram_gen"], - ) - check = "" - if generator == "generate_ram": - pass - elif rtl_module: - check = "-check_ports " + " ".join(["$(location %s)" % r for r in rtl]) - if generator != "generate_ram": - native.genrule( - name = name + "_gen_v", - srcs = [spec, _TECH_LEF, _CELL_LEF] + rtl, - outs = [name + "_gen.v"], - cmd = """ -grep -v '^[[:space:]]*memory[[:space:]]' $(location {spec}) > $(@D)/{name}.regfile -cat > $(@D)/{name}.tcl < $(@D)/{name}.log 2>&1 || {{ cat $(@D)/{name}.log; exit 1; }} -sed 's/^module {module}(/module {module}_gen(/' $(@D)/{name}.raw.v > $@ -grep -q '^module {module}_gen(' $@ || {{ echo 'no module {module} in the netlist'; exit 1; }} -""".format( - name = name, - tech = _TECH_LEF, - cell = _CELL_LEF, - spec = spec, - check = check, - module = module, - ), - tools = ["@openroad"], - ) + native.genrule( + name = name + "_gen_v", + srcs = [spec, _TECH_LEF, _CELL_LEF, _REGFILE_RAM] + _LIBS, + outs = [name + "_gen.v"], + cmd = " ".join([ + "grep -v '^[[:space:]]*memory[[:space:]]' $(location %s) > $(@D)/%s.regfile &&" % (spec, name), + "$(execpath :ram_gen)", + "--regfile-ram $(location %s)" % _REGFILE_RAM, + "--spec $(@D)/%s.regfile" % name, + "--module " + module, + "--openroad $(location @openroad//:openroad)", + "--lef $(location %s) --lef $(location %s)" % (_TECH_LEF, _CELL_LEF), + ] + ["--lib $(location %s)" % lib for lib in _LIBS] + [ + "--out $@", + ]), + tools = ["@openroad", ":ram_gen"], + ) tie_args = " ".join(["--tie %s=%s" % (k, v) for k, v in ties.items()]) native.genrule( name = name + "_tb", diff --git a/test/regfile/regfile_top.v b/test/regfile/regfile_top.v index 43fdf1c67..87502c8c9 100644 --- a/test/regfile/regfile_top.v +++ b/test/regfile/regfile_top.v @@ -1,7 +1,7 @@ // A 16 x 8 register file with two read ports and two write ports, // behavioural, as RTL writes one. With AUTO_MEMORIES_REGFILES naming its // spec the flow never synthesises this module: OpenROAD's -// generate_regfile builds it of placed standard cells instead. +// generate_ram builds it of placed standard cells instead. module RegFile( input clock, input [3:0] io_r0_addr, diff --git a/test/regfile/riscv32i/BUILD.bazel b/test/regfile/riscv32i/BUILD.bazel index 1a7052d4d..8c7aaef9e 100644 --- a/test/regfile/riscv32i/BUILD.bazel +++ b/test/regfile/riscv32i/BUILD.bazel @@ -1,13 +1,22 @@ load("@orfs_designs//:designs.bzl", "DESIGNS") load("//:openroad.bzl", "odb_debug", "orfs_flow") -# riscv32i's register file in each shape generate_regfile offers, on +# riscv32i's register file in each shape generate_ram offers, on # ORFS's own riscv32i config (62 %, its io.tcl), to global route: flops # (ORFS's riscv32i), inlined (synthesis reads the generated netlist), # netlist (macro-placed, then dissolved) and macro (macro-placed, kept). # A study, not a gate: every target is manual. package(default_visibility = ["//visibility:private"]) +# simulated against riscv32i's RTL in test/regfile/cores +exports_files( + [ + "inlined.regfile", + "inlined_verilog.regfile", + ], + visibility = ["//test/regfile/cores:__pkg__"], +) + RISCV32I = DESIGNS["asap7/riscv32i"] # DESIGNS' labels are ORFS's own, relative to its repository. diff --git a/test/regfile/sim/BUILD.bazel b/test/regfile/sim/BUILD.bazel index 27fe49ce9..b052b0ec7 100644 --- a/test/regfile/sim/BUILD.bazel +++ b/test/regfile/sim/BUILD.bazel @@ -1,10 +1,7 @@ -# What generate_regfile builds computes what the RTL it replaces does: -# riscv32i's register file as generate_regfile writes it, simulated beside -# src/riscv32i/regfile.v under random reads and writes, every read -# compared. One netlist per write style: a hold mux per bit, and a clock -# gate per word; and the clock gate with its periphery as assigns -# (`periphery verilog`), inlined and, in mode netlist, as a wrapper -# around the core's own netlist (regfile_core.v). +# generate_ram's RAMs (OpenROAD patches 0011 to 0023) simulated beside +# their own behavioral models under random reads and writes, every read +# compared, in the shapes the patches add. The register files of real +# designs are simulated against their RTL in test/regfile/cores. load("@rules_cc//cc:defs.bzl", "cc_test") load("@rules_verilator//verilator:defs.bzl", "verilator_cc_library") load("@rules_verilog//verilog:defs.bzl", "verilog_library") @@ -24,93 +21,6 @@ stdcell_verilog( ], ) -[ - [ - genrule( - name = "regfile_%s_v" % style, - srcs = [ - ":regfile.regfile", - "@orfs//flow/designs/src/riscv32i:regfile.v", - "@orfs//flow:platforms/asap7/lef/asap7_tech_1x_201209.lef", - "@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef", - ], - outs = ["regfile_%s.v" % style] + ( - ["regfile_core.v"] if "periphery verilog" in lines and "mode netlist" in lines else [] - ), - cmd = """ -grep -v '^write_style' $(location :regfile.regfile) > $(@D)/regfile_{style}.regfile -{extra} -cat > $(@D)/regfile_{style}.tcl < $(@D)/regfile_{style}.log 2>&1 || {{ cat $(@D)/regfile_{style}.log; exit 1; }} -sed -e 's/^module regfile(/module regfile_gen(/' -e '/^(\\* blackbox \\*)$$/,$$d' $(@D)/regfile_{style}.gen.v > $(@D)/regfile_{style}.v -""".format( - extra = "\n".join([ - "echo '%s' >> $(@D)/regfile_%s.regfile" % (line, style) - for line in lines - ]), - style = style, - ), - tools = ["@openroad"], - ), - verilog_library( - name = "tb_%s_rtl" % style, - srcs = [ - "tb_top.v", - ":regfile_%s.v" % style, - ] + ( - [":regfile_core.v"] if "periphery verilog" in lines and "mode netlist" in lines else [] - ) + [ - ":asap7_stdcell.v", - ":asap7_stdcell_empty.v", - "@orfs//flow/designs/src/riscv32i:regfile.v", - ], - ), - verilator_cc_library( - name = "tb_%s" % style, - module = ":tb_%s_rtl" % style, - module_top = "tb_top", - trace_mode = "none", - vopts = [ - "-Wno-fatal", - "--x-initial", - "0", - ], - ), - cc_test( - name = "regfile_%s_sim_test" % style, - size = "small", - srcs = ["tb_main.cc"], - deps = [":tb_%s" % style], - ), - ] - for style, lines in [ - ("mux", []), - ( - "clock_gate", - ["write_style clock_gate"], - ), - ( - "clock_gate_verilog", - [ - "write_style clock_gate", - "periphery verilog", - ], - ), - ( - "netlist_verilog", - [ - "mode netlist", - "write_style clock_gate", - "periphery verilog", - ], - ), - ] -] - # generate_ram with two write ports (OpenROAD patch 0011): its netlist # beside its own behavioral model on Nangate45, whose tristate buffers # make the read bitlines, under random writes on both ports, a quarter @@ -238,10 +148,14 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_and_or_zero", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -zero_word 3", "tb_ram_2w", 8), ("ram_2w_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R", "tb_ram_2w", 8), ("ram_2w_asap7_zero", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -zero_word 0", "tb_ram_2w", 8), + ("ram_2w_or", NANGATE45, "-storage_cell DFF_X1 -write_priority or", "tb_ram_2w", 8), + ("ram_2w_or_asap7_mux", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -write_priority or", "tb_ram_2w", 8), ("ram_2w_rst", NANGATE45, "-storage_cell DFFRS_X1 -reset_value 0xa5", "tb_ram_2w_rst", 8), ("ram_2w_rst_and_or", NANGATE45, "-storage_cell DFFRS_X1 -read_style and_or -reset_value 0xa5", "tb_ram_2w_rst", 8), ("ram_2w_rst_asap7", ASAP7, "-storage_cell DFFASRHQNx1_ASAP7_75t_R -reset_value 0xa5", "tb_ram_2w_rst", 8), ("ram_2w_banks", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 2 -bank_order interleaved", "tb_ram_2w", 8), + ("ram_2w_banks_contiguous", NANGATE45, "-storage_cell DFF_X1 -banks 4 -bank_columns 2 -bank_order interleaved -bank_column_layout contiguous", "tb_ram_2w", 8), + ("ram_2w_banks_contiguous_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 4 -bank_column_layout contiguous -bit_folds 3 -mask_size 3 -write_style mux -write_priority or", "tb_ram_2w", 8), ("ram_2w_banks_and_or", NANGATE45, "-storage_cell DFF_X1 -read_style and_or -banks 2 -bank_columns 2", "tb_ram_2w", 8), ("ram_2w_banks_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2 -bank_order interleaved -zero_word 0", "tb_ram_2w", 8), ("ram_2w_banks12_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -banks 4 -bank_columns 2", "tb_ram_2w", 12), @@ -257,6 +171,9 @@ sed -i 's/^module RAM{words}x8 /module RAM8x8 /' $(location {name}_model.v) ("ram_2w_unplaced_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -write_style mux -banks 4 -bank_columns 2 -periphery unplaced -pin_layer M4", "tb_ram_2w", 8), ("ram_2w_cells_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -cells {inv INVx1_ASAP7_75t_R and2 AND2x2_ASAP7_75t_R buffer BUFx2_ASAP7_75t_R aoi22 AOI22x1_ASAP7_75t_R ao22 AO22x2_ASAP7_75t_R or2 OR2x2_ASAP7_75t_R nand2 NAND2x1_ASAP7_75t_R nor2 NOR2x1_ASAP7_75t_R} -name RAM8x8", "tb_ram_2w", 8), ("ram_2w_folds", NANGATE45, "-storage_cell DFF_X1 -mask_size 4 -bit_folds 2 -decoder word", "tb_ram_2w", 8), + # 8 bits in 3 folds of 3: the last fold short, one pad column + ("ram_2w_folds_short", NANGATE45, "-storage_cell DFF_X1 -mask_size 3 -bit_folds 3 -decoder word", "tb_ram_2w", 8), + ("ram_2w_folds_short_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -mask_size 3 -bit_folds 3 -write_style mux -write_priority or", "tb_ram_2w", 8), ("ram_2w_folds_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -mask_size 2 -bit_folds 4 -banks 4 -bank_columns 2 -bank_order interleaved -write_style mux -read_latency 1", "tb_ram_2w", 8), ("ram_2w_periphery_verilog_asap7", ASAP7, "-storage_cell DFFHQNx1_ASAP7_75t_R -periphery verilog -pin_layer M4 -wrapper_verilog $(@D)/ram_2w_periphery_verilog_asap7_wrap.v -banks 4 -bank_columns 2 -write_style mux", "tb_ram_2w", 8), ("ram_2w_periphery_verilog", NANGATE45, "-storage_cell DFF_X1 -periphery verilog -pin_layer metal4 -wrapper_verilog $(@D)/ram_2w_periphery_verilog_wrap.v", "tb_ram_2w", 8), diff --git a/test/regfile/sim/regfile.regfile b/test/regfile/sim/regfile.regfile deleted file mode 100644 index 04120ccd6..000000000 --- a/test/regfile/sim/regfile.regfile +++ /dev/null @@ -1,17 +0,0 @@ -# riscv32i's `regfile` (src/riscv32i/regfile.v) as generate_regfile builds -# it, for simulation against that RTL: 32 x 32, two combinational reads, -# one write, x0 reads 0. BUILD.bazel appends the write style. -module regfile -words 32 -bits 32 -clock clk -read ra1 rd1 -read ra2 rd2 -write wa3 wd3 we3 -zero_word 0 -cell icg ICGx1_ASAP7_75t_R -cell flop DFFHQNx1_ASAP7_75t_R -cell and2 AND2x2_ASAP7_75t_R -cell or2 OR2x2_ASAP7_75t_R -cell ao22 AO22x2_ASAP7_75t_R -cell inv INVx1_ASAP7_75t_R diff --git a/test/regfile/sim/tb_main.cc b/test/regfile/sim/tb_main.cc deleted file mode 100644 index 5de7d4673..000000000 --- a/test/regfile/sim/tb_main.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Random reads and writes on riscv32i's register file and on the netlist -// generate_regfile writes for it; every read of both ports compared. -// Every word is written once first, unchecked: an unwritten word reads -// what each side's power-up state happens to be (the generated flops -// hold the inverse of the value). -#include -#include -#include - -#include "Vtb_top.h" - -namespace { - -int Check(Vtb_top& tb, int cycle) { - tb.eval(); - if (tb.rd1_rtl != tb.rd1_gen || tb.rd2_rtl != tb.rd2_gen) { - std::printf( - "cycle %d: ra1 %u ra2 %u: rtl %08x %08x, generated %08x %08x\n", - cycle, tb.ra1, tb.ra2, tb.rd1_rtl, tb.rd2_rtl, tb.rd1_gen, - tb.rd2_gen); - return 1; - } - return 0; -} - -// One clock: inputs set while the clock is low, the write on its rising -// edge; with `check`, both reads compared before and after it. -int Cycle(Vtb_top& tb, int cycle, bool check, bool we, int wa, uint32_t wd, - int ra1, int ra2) { - tb.clk = 0; - tb.we3 = we; - tb.wa3 = wa; - tb.wd3 = wd; - tb.ra1 = ra1; - tb.ra2 = ra2; - tb.eval(); - int bad = check ? Check(tb, cycle) : 0; - tb.clk = 1; - tb.eval(); - bad += check ? Check(tb, cycle) : 0; - return bad; -} - -} // namespace - -int main() { - Vtb_top tb; - std::mt19937 rng(1); - int bad = 0; - int cycle = 0; - for (int w = 0; w < 32; ++w, ++cycle) { - Cycle(tb, cycle, false, true, w, rng(), w, w); - } - for (int i = 0; i < 20000 && bad < 10; ++i, ++cycle) { - bad += Cycle(tb, cycle, true, rng() % 2, rng() % 32, rng(), rng() % 32, - rng() % 32); - } - std::printf("%d cycles, %d mismatches\n", cycle, bad); - return bad == 0 ? 0 : 1; -} diff --git a/test/regfile/sim/tb_top.v b/test/regfile/sim/tb_top.v deleted file mode 100644 index 78a38e7bb..000000000 --- a/test/regfile/sim/tb_top.v +++ /dev/null @@ -1,23 +0,0 @@ -// riscv32i's register file and the netlist generate_regfile writes for -// it, on the same inputs, both reads of each side out. -module tb_top ( - input clk, - input we3, - input [4:0] ra1, - input [4:0] ra2, - input [4:0] wa3, - input [31:0] wd3, - output [31:0] rd1_rtl, - output [31:0] rd2_rtl, - output [31:0] rd1_gen, - output [31:0] rd2_gen -); - regfile rtl ( - .clk(clk), .we3(we3), .ra1(ra1), .ra2(ra2), .wa3(wa3), .wd3(wd3), - .rd1(rd1_rtl), .rd2(rd2_rtl) - ); - regfile_gen gen ( - .clk(clk), .we3(we3), .ra1(ra1), .ra2(ra2), .wa3(wa3), .wd3(wd3), - .rd1(rd1_gen), .rd2(rd2_gen) - ); -endmodule diff --git a/test/structured_gen_lec/BUILD b/test/structured_gen_lec/BUILD index fd94b3cb2..4cf68127f 100644 --- a/test/structured_gen_lec/BUILD +++ b/test/structured_gen_lec/BUILD @@ -100,14 +100,14 @@ regfile_lec( spec_args = "--spec-latency 0", ) -# OpenROAD's generate_regfile on the same fixtures, in both write styles. +# OpenROAD's generate_ram on the same fixtures, in both write styles. # A clock gate per word puts the write enable on the clock, which # kepler-formal's combinational check cannot model: those flops' next # state is left out (skip_gated_clock_flops, experimental, patch # kepler-formal-0002) and the rest -- every read, through every flop's # output -- is compared. -GENERATE_REGFILE_LEC = [ - "%s%d_%s_generate_regfile_lec_test" % ( +GENERATE_RAM_LEC = [ + "%s%d_%s_generate_ram_lec_test" % ( shape, sizes[0], style, @@ -120,7 +120,7 @@ GENERATE_REGFILE_LEC = [ ] [regfile_lec( - name = "%s%d_%s_generate_regfile_lec_test" % ( + name = "%s%d_%s_generate_ram_lec_test" % ( shape, sizes[0], style, @@ -129,7 +129,7 @@ GENERATE_REGFILE_LEC = [ sizes[0], args, ), - generator = "generate_regfile", + generator = "generate_ram", module = "%s%d" % ( shape.capitalize(), sizes[0], @@ -144,10 +144,10 @@ GENERATE_REGFILE_LEC = [ # The skip must not hide a read-path bug: the same spec error as above, # clock-gated, still caught. regfile_lec( - name = "fp8_unregistered_clock_gate_generate_regfile_lec_test", + name = "fp8_unregistered_clock_gate_generate_ram_lec_test", args = "--words 8 --bits 4 --reads 14 --writes 7 --latency 1", expect_equivalent = False, - generator = "generate_regfile", + generator = "generate_ram", module = "Fp8gu", skip_gated_clock_flops = True, spec_args = "--spec-latency 0", @@ -159,8 +159,8 @@ test_suite( tags = ["manual"], tests = ["%s%d_lec_test" % (shape, words) for shape, (_, sizes) in SHAPES.items() for words in sizes] + [ "fp8_unregistered_lec_test", - ] + GENERATE_REGFILE_LEC + [ - "fp8_unregistered_clock_gate_generate_regfile_lec_test", + ] + GENERATE_RAM_LEC + [ + "fp8_unregistered_clock_gate_generate_ram_lec_test", ], ) diff --git a/test/structured_gen_lec/regfile_lec.bzl b/test/structured_gen_lec/regfile_lec.bzl index bab337199..851496539 100644 --- a/test/structured_gen_lec/regfile_lec.bzl +++ b/test/structured_gen_lec/regfile_lec.bzl @@ -7,6 +7,8 @@ ASAP7_LEFS = [ "@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef", ] +_REGFILE_RAM = "@orfs//flow:scripts/memories/regfile_ram.py" + LIBERTY = [ "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib", ":asap7_simple.lib", @@ -26,6 +28,15 @@ opt_clean -purge write_verilog -noattr {raw} """ +# kepler-formal pairs flops by their full name: the wrapper's RAM +# instance (ram) is flattened away so the flops keep the RTL's names. +_FLATTEN_SCRIPT = """read_liberty -lib {libs} +read_verilog {hier} +hierarchy -top {module} +flatten +write_verilog -noattr {flat} +""" + def regfile_lec( name, module, @@ -43,10 +54,11 @@ def regfile_lec( args: lec_fixture.py's shape and size arguments. expect_equivalent: False for a case that must be caught. spec_args: extra lec_fixture.py arguments for the spec alone. - generator: structured_gen, or generate_regfile (OpenROAD patch - 0010), which builds the gate netlist from the same spec. + generator: structured_gen, or generate_ram (through ORFS's + regfile_ram.py, the netlist AUTO_MEMORIES_REGFILES inlines), + which builds the gate netlist from the same spec. spec_lines: lines appended to the spec for the gate netlist - (`write_style clock_gate`); generate_regfile only. + (`write_style clock_gate`); generate_ram only. skip_gated_clock_flops: the lec_test option of that name, for a clock-gated gate netlist. """ @@ -100,7 +112,7 @@ def regfile_lec( else: native.genrule( name = name + "_gate", - srcs = [name + ".spec"] + ASAP7_LEFS, + srcs = [name + ".spec", _REGFILE_RAM] + ASAP7_LEFS + LIBERTY, outs = [name + "_gate.v"], cmd = " && ".join([ "cp $(location {}.spec) $(RULEDIR)/{}_gate.spec".format(name, name), @@ -109,14 +121,34 @@ def regfile_lec( "echo '{}' >> $(RULEDIR)/{}_gate.spec".format(line, name) for line in spec_lines ] + [ - "printf 'read_lef %s\\nread_lef %s\\ngenerate_regfile -spec %s -verilog %s\\n' $(location {t}) $(location {c}) $(RULEDIR)/{n}_gate.spec $@ > $(RULEDIR)/{n}_gate.tcl".format( - n = name, - t = ASAP7_LEFS[0], - c = ASAP7_LEFS[1], + " ".join([ + "$(execpath //test/regfile/cores:ram_gen)", + "--regfile-ram $(location {})".format(_REGFILE_RAM), + "--spec $(RULEDIR)/{}_gate.spec".format(name), + "--module " + module, + "--openroad $(location @openroad//:openroad)", + "--lef $(location {}) --lef $(location {})".format(ASAP7_LEFS[0], ASAP7_LEFS[1]), + ] + ["--lib $(location {})".format(lib) for lib in LIBERTY] + [ + "--suffix ''", + "--out $(RULEDIR)/{}_hier.v".format(name), + ]), + "printf '%s' '{}' > $(RULEDIR)/{}_flat.ys".format( + _FLATTEN_SCRIPT.format( + libs = " ".join(["$(location {})".format(lib) for lib in LIBERTY]), + hier = "$(RULEDIR)/{}_hier.v".format(name), + module = module, + flat = "$(RULEDIR)/{}_flat.v".format(name), + ), + name, ), - "$(location @openroad//:openroad) -exit -no_init -no_splash $(RULEDIR)/{}_gate.tcl > /dev/null".format(name), + "$(location @yosys//:yosys) -q -s $(RULEDIR)/{}_flat.ys".format(name), + "sed 's/[\\\\]ram[.]/\\\\/' $(RULEDIR)/{}_flat.v > $@".format(name), ]), - tools = ["@openroad//:openroad"], + tools = [ + "//test/regfile/cores:ram_gen", + "@openroad//:openroad", + "@yosys//:yosys", + ], ) lec_test( name = name, diff --git a/test/structured_netlist/BUILD.bazel b/test/structured_netlist/BUILD.bazel index 2ab10aa61..51f20837f 100644 --- a/test/structured_netlist/BUILD.bazel +++ b/test/structured_netlist/BUILD.bazel @@ -8,8 +8,8 @@ load(":scaffold.bzl", "array_scaffold") # miniature planned parent and the parent itself. A 305 um array grows # nets the resizer wants to buffer, which the small files never do # (inventory entry 16); CTS rewires its flops and seats its buffers in the -# service columns at the real count. The outlines are the generator's -# .def DIEAREA for each spec; a stale pair fails at floorplan. +# service columns at the real count. The outlines are generate_ram's, +# for each spec in the netlist shape; a stale pair fails at floorplan. py_binary( name = "scaffold_gen", srcs = ["scaffold_gen.py"], @@ -20,26 +20,29 @@ XS_SPECS = "//test/coremark_joule/designs/asap7/xiangshan:" array_scaffold( name = "RenameBufferFile", - height_um = 192.24, + height_um = 190.35, + periphery_um2 = 7027, spec = XS_SPECS + "RenameBufferFile.regfile", - width_um = 306.504, + width_um = 129.06, ) array_scaffold( name = "RobEntryFile", - height_um = 192.51, + height_um = 95.31, + periphery_um2 = 7027, spec = XS_SPECS + "RobEntryFile.regfile", - width_um = 318.384, + width_um = 295.002, ) array_scaffold( name = "IntRegFile", - height_um = 243.27, + height_um = 242.19, + periphery_um2 = 3236, spec = XS_SPECS + "IntRegFile.regfile", - width_um = 406.404, + width_um = 192.294, ) -# generate_regfile's golden case (tools/structured_gen:golden_test). +# generate_ram's golden case (tools/structured_gen:golden_test). exports_files( ["SmallFile.regfile"], visibility = ["//tools/structured_gen:__pkg__"], diff --git a/test/structured_netlist/scaffold.bzl b/test/structured_netlist/scaffold.bzl index cac790bcf..af1793de0 100644 --- a/test/structured_netlist/scaffold.bzl +++ b/test/structured_netlist/scaffold.bzl @@ -10,18 +10,26 @@ CORE_UM = 10.0 # die to core def _r(x): return int(x * 1000 + 0.5) / 1000.0 -def array_scaffold(name, spec, width_um, height_um): +def array_scaffold(name, spec, width_um, height_um, periphery_um2): """The scaffold flow for one spec: _scaffold_, to CTS: a smoke test that the array dissolves and CTS seats its buffers; nothing reads a route. Args: name: the module the spec names (RenameBufferFile, ...). spec: the .regfile label, mode netlist. - width_um, height_um: the array's outline as structured_gen draws it - (its .def DIEAREA); the die is the array plus a ring of flops. A + width_um, height_um: the array's outline as generate_ram draws it + in the netlist shape (regfile_ram.py's _ram.outline); the + die is the array plus a ring of flops. A wrong pair fails at floorplan (FLW-0004, the array leaves the core), so the numbers are checked by the flow, not trusted. + periphery_um2: the cell area generate_ram leaves outside the + outline (decoders, select and input buffers) for the parent to + place. The ring is widened to hold it at the flow's 0.5 placement + density, beside the parent's flops. """ + + # the periphery at density 0.5 spread along the ring's length + ring = RING_UM + 2 * periphery_um2 / (2 * (width_um + height_um + 4 * RING_UM)) top = name + "_scaffold" native.genrule( name = top + "_rtl", @@ -31,13 +39,13 @@ def array_scaffold(name, spec, width_um, height_um): spec, top, top, - _r(CORE_UM + RING_UM), - _r(CORE_UM + RING_UM), + _r(CORE_UM + ring), + _r(CORE_UM + ring), ), tools = [":scaffold_gen"], ) - die_w = width_um + 2 * (CORE_UM + RING_UM) - die_h = height_um + 2 * (CORE_UM + RING_UM) + die_w = width_um + 2 * (CORE_UM + ring) + die_h = height_um + 2 * (CORE_UM + ring) orfs_flow( name = top, arguments = TURNAROUND_ARGS | { diff --git a/test/structured_netlist/scaffold_gen.py b/test/structured_netlist/scaffold_gen.py index ed393eb17..26236eaba 100644 --- a/test/structured_netlist/scaffold_gen.py +++ b/test/structured_netlist/scaffold_gen.py @@ -159,9 +159,16 @@ def main(argv): f.write("\n") f.write(parent(spec, top, "u_file")) with open(a.macro_placement, "w") as f: - f.write("# %s's lower-left corner in the parent, um\n" % spec["module"]) f.write( - "place_macro -macro_name u_file -location {%s} -orientation R0\n" % a.corner + "# %s's lower-left corner in the parent, um: the macro is\n" + "# generate_ram's RAM, ram, in the wrapper in the module's place\n" + % spec["module"] + ) + f.write( + "foreach name {u_file u_file/ram u_file.ram} {\n" + ' if { [[ord::get_db_block] findInst $name] ne "NULL" } { break }\n' + "}\n" + "place_macro -macro_name $name -location {%s} -orientation R0\n" % a.corner ) print("%s: %d ports, parent %s" % (spec["module"], len(ports(spec)), top)) diff --git a/tools/macro_select/plan_floorplan.py b/tools/macro_select/plan_floorplan.py index f205cba16..567190189 100644 --- a/tools/macro_select/plan_floorplan.py +++ b/tools/macro_select/plan_floorplan.py @@ -752,15 +752,20 @@ def place_exact(m, segs, tech): puts "place_macros.tcl: $bands soft placement blockage(s) over the blocks' bands; the rows stay" # The plan's register files (AUTO_MEMORIES_REGFILES in mode netlist) are # macros until the end of this step, each found by its instance and placed -# where the plan put it; they dissolve into their cells after it. +# where the plan put it; they dissolve into their cells after it. The +# macro is the instance itself, or generate_ram's RAM, ram, inside the +# wrapper that takes the module's place. foreach {{inst x y}} {{ {netlists} }} {{ - set i [$block findInst $inst] + foreach name [list $inst $inst/ram $inst.ram] {{ + set i [$block findInst $name] + if {{ $i ne "NULL" }} {{ break }} + }} if {{ $i eq "NULL" }} {{ utl::error FLW 2 "plan: no register file instance $inst" }} - place_macro -macro_name $inst -location [list $x $y] -orientation R0 -exact + place_macro -macro_name [$i getName] -location [list $x $y] -orientation R0 -exact $i setPlacementStatus FIRM puts "place_macros.tcl: register file $inst at $x $y um, R0" }} diff --git a/tools/structured_gen/BUILD.bazel b/tools/structured_gen/BUILD.bazel index 707bc185c..e7f66543b 100644 --- a/tools/structured_gen/BUILD.bazel +++ b/tools/structured_gen/BUILD.bazel @@ -32,6 +32,18 @@ ASAP7_LEFS = [ "@orfs//flow:platforms/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef", ] +# generate_ram matches its cells by their liberty functions. +ASAP7_LIBS = [ + "@orfs//flow:platforms/asap7/lib/NLDM/asap7sc7p5t_%s.lib%s" % (lib, gz) + for lib, gz in [ + ("AO_RVT_TT_nldm_211120", ".gz"), + ("INVBUF_RVT_TT_nldm_220122", ".gz"), + ("OA_RVT_TT_nldm_211120", ".gz"), + ("SEQ_RVT_TT_nldm_220123", ""), + ("SIMPLE_RVT_TT_nldm_211120", ".gz"), + ] +] + cc_test( name = "registered_read_test", size = "small", @@ -50,9 +62,9 @@ cc_test( deps = [":regfile"], ) -# OpenROAD's generate_regfile (patch 0010) builds every spec and writes -# all its views. It was byte for byte this tool's output -# until the read gates and the clock gate moved it on. The tiny synthetic +# OpenROAD's generate_ram, through ORFS's regfile_ram.py, builds every +# spec and writes all its views. generate_regfile's output was byte for +# byte this tool's until the read gates and the clock gate moved it on. The tiny synthetic # specs in golden/ cover every spec feature (banks, bank columns, bit # folds, registered read with the RTL's names, banked and interleaved # reads, the zero word, netlist mode) in seconds. @@ -80,18 +92,24 @@ GOLDEN_XIANGSHAN = [ size = size, srcs = ["golden_test.sh"], args = [ + "$(rootpath //test/regfile/cores:ram_gen)", + "$(rootpath @orfs//flow:scripts/memories/regfile_ram.py)", "$(rootpath @openroad//:openroad)", ] + ["$(rootpath {})".format(l) for l in ASAP7_LEFS] + [ + "'{}'".format(" ".join(["$(rootpath {})".format(l) for l in ASAP7_LIBS])), + ] + [ "$(rootpath {})".format(s) for s in specs ], data = [ + "//test/regfile/cores:ram_gen", "@openroad", - ] + ASAP7_LEFS + specs, + "@orfs//flow:scripts/memories/regfile_ram.py", + ] + ASAP7_LEFS + ASAP7_LIBS + specs, tags = tags, ) for name, size, specs, tags in [ - ("golden_test", "small", GOLDEN_TINY, []), + ("golden_test", "medium", GOLDEN_TINY, []), ( "golden_xiangshan_test", "enormous", diff --git a/tools/structured_gen/golden_test.sh b/tools/structured_gen/golden_test.sh index 97e69136f..701b760cf 100755 --- a/tools/structured_gen/golden_test.sh +++ b/tools/structured_gen/golden_test.sh @@ -1,36 +1,45 @@ #!/usr/bin/env bash -# OpenROAD's generate_regfile (carried patch 0010) builds every spec here -# and writes all its views. The specs cover every spec feature; whether -# what they build computes the RTL's function is test/regfile/sim's to -# check. This tool's own output is no longer the reference: -# generate_regfile has moved past it (inverting read gates, the clock -# gate per word). -# golden_test.sh ... +# OpenROAD's generate_ram, through ORFS's translation of a spec +# (regfile_ram.py, what AUTO_MEMORIES_REGFILES runs), builds every spec +# here in the spec's mode (a macro unless it says netlist) and writes all +# its views. The specs cover every spec feature; whether what they build +# computes the RTL's function is test/regfile/sim's to check. This tool's +# own output is no longer the reference: generate_ram has moved past it +# (inverting read gates, the clock gate per word). +# golden_test.sh +# ... +# is one argument, the liberty files separated by spaces. set -euo pipefail -OPENROAD="$1" TECH="$2" CELLS="$3" -shift 3 +RAM_GEN="$1" REGFILE_RAM="$2" OPENROAD="$3" TECH="$4" CELLS="$5" LIBS="$6" +shift 6 OUT="${TEST_TMPDIR:-$(mktemp -d)}" FAILS=0 +lib_args=() +for lib in $LIBS; do + lib_args+=(--lib "$lib") +done for spec in "$@"; do name="$(basename "$spec" .regfile)" + module="$(sed -n 's/^module[[:space:]]*//p' "$spec")" + shape="$(sed -n 's/^mode[[:space:]]*//p' "$spec")" + [ "$shape" = netlist ] || shape=macro b="$OUT/$name" - mkdir -p "$b" - cat >"$b/run.tcl" <"$b/log" 2>&1; then - echo "FAIL: $name: generate_regfile failed" - tail -3 "$b/log" + if ! "$RAM_GEN" --regfile-ram "$REGFILE_RAM" --spec "$spec" \ + --module "$module" --openroad "$OPENROAD" --lef "$TECH" \ + --lef "$CELLS" "${lib_args[@]}" --shape "$shape" --out "$b" \ + >"$OUT/$name.log" 2>&1; then + echo "FAIL: $name: generate_ram failed" + tail -3 "$OUT/$name.log" FAILS=$((FAILS + 1)) continue fi - for f in rf.v rf.def rf.lef rf.lib rf_pre_layout.lib; do + block="${module}_ram" + [ -s "$b/${block}_core.odb" ] && block="${block}_core" + for f in "$block.odb" "$block.v" "$block.place" "$block.lef" "$block.lib"; do [ -s "$b/$f" ] || { echo "FAIL: $name: no $f"; FAILS=$((FAILS + 1)); } done - echo "ok: $name" + echo "ok: $name ($shape)" done [ "$FAILS" -eq 0 ] || { echo "$FAILS failed"; exit 1; } echo "all built" diff --git a/tools/structured_gen/test/BUILD.bazel b/tools/structured_gen/test/BUILD.bazel index a7dd6aec2..e0509071f 100644 --- a/tools/structured_gen/test/BUILD.bazel +++ b/tools/structured_gen/test/BUILD.bazel @@ -62,7 +62,7 @@ build_test( # The same register file replaced *by name* inside a parent: the parent's # RTL instantiates rf32x32, AUTO_MEMORIES_REGFILES lists the spec, and the -# memories step runs generate_regfile, writes the views beside the +# memories step runs generate_ram, writes the views beside the # AUTO_MEMORIES ones and blackboxes the module. The floorplan then places # one macro. This is the hook the XiangShan register files use. orfs_flow( @@ -92,8 +92,9 @@ build_test( targets = [":rf_parent_floorplan"], ) -# The module reached the netlist as a cell, not as flops: blackboxes.txt -# names it and 1_2_yosys.v instantiates it. +# The module reached the netlist as a cell, not as flops: generate_ram's +# block, rf32x32_ram, in the wrapper that takes the module's place; +# blackboxes.txt names it and 1_2_yosys.v instantiates it. genrule( name = "rf_parent_replaced", srcs = [":rf_parent_synth"], @@ -101,8 +102,8 @@ genrule( cmd = "files=$$(echo $(locations :rf_parent_synth) | tr ' ' '\\n'); " + "bb=$$(echo \"$$files\" | grep '/memories$$')/blackboxes.txt; " + "net=$$(echo \"$$files\" | grep '/1_2_yosys.v$$'); " + - "grep -q '^rf32x32 ' $$bb ||{ echo 'rf32x32 not in blackboxes.txt'; exit 1; }; " + - "grep -q '^ *rf32x32 ' $$net || { echo 'rf32x32 not a cell in the netlist'; exit 1; }; " + + "grep -q '^rf32x32_ram ' $$bb ||{ echo 'rf32x32_ram not in blackboxes.txt'; exit 1; }; " + + "grep -q '^ *rf32x32_ram ' $$net || { echo 'rf32x32_ram not a cell in the netlist'; exit 1; }; " + "echo 'rf32x32 replaced by the generated macro' > $@", )