mirror of https://github.com/openXC7/prjxray.git
Merge pull request #458 from mcmasterg/iob_supertag
Iob supertag, mergedb improvement, groupmask util
This commit is contained in:
commit
78c86a3300
|
|
@ -0,0 +1,20 @@
|
|||
N := 1
|
||||
include ../fuzzer.mk
|
||||
|
||||
SEGDATAS=$(addsuffix /segdata_liob33.txt,$(SPECIMENS))
|
||||
|
||||
database: build/segbits_liob33.db
|
||||
|
||||
build/segbits_liob33.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} -c -1 -o build/segbits_liob33.rdb $(SEGDATAS)
|
||||
|
||||
build/segbits_liob33.db: build/segbits_liob33.rdb
|
||||
python3 ${XRAY_DIR}/utils/groupmask.py $^ $@
|
||||
${XRAY_MASKMERGE} build/mask_liob33.db $(SEGDATAS)
|
||||
|
||||
pushdb:
|
||||
${XRAY_MERGEDB} liob33 build/segbits_liob33.db
|
||||
${XRAY_MERGEDB} mask_liob33 build/mask_liob33.db
|
||||
|
||||
.PHONY: database pushdb
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from prjxray.segmaker import Segmaker
|
||||
from prjxray import segmaker
|
||||
|
||||
segmk = Segmaker("design.bits")
|
||||
|
||||
print("Loading params")
|
||||
f = open('params.csv', 'r')
|
||||
f.readline()
|
||||
for l in f:
|
||||
l = l.strip()
|
||||
site, name, dir_, cell = l.split(',')
|
||||
segmaker.add_site_group_zero(
|
||||
segmk, site, "MACRO.", ("INPUT", "OUTPUT"), "", dir_.upper())
|
||||
|
||||
segmk.compile()
|
||||
segmk.write()
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
source ${XRAY_DIR}/utils/top_generate.sh
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
source "$::env(XRAY_DIR)/utils/utils.tcl"
|
||||
|
||||
proc make_io_pin_sites {} {
|
||||
# get all possible IOB pins
|
||||
foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
|
||||
set site [get_sites -of_objects $pad]
|
||||
if {[llength $site] == 0} {
|
||||
continue
|
||||
}
|
||||
if [string match IOB33* [get_property SITE_TYPE $site]] {
|
||||
dict append io_pin_sites $site $pad
|
||||
}
|
||||
}
|
||||
return $io_pin_sites
|
||||
}
|
||||
|
||||
proc load_pin_lines {} {
|
||||
# IOB_X0Y103 clk input
|
||||
# IOB_X0Y129 do[0] output
|
||||
|
||||
set fp [open "params.csv" r]
|
||||
set pin_lines {}
|
||||
for {gets $fp line} {$line != ""} {gets $fp line} {
|
||||
lappend pin_lines [split $line ","]
|
||||
}
|
||||
close $fp
|
||||
return $pin_lines
|
||||
}
|
||||
|
||||
proc loc_pins {} {
|
||||
set pin_lines [load_pin_lines]
|
||||
set io_pin_sites [make_io_pin_sites]
|
||||
|
||||
set fp [open "design.csv" w]
|
||||
puts $fp "port,site,tile,pin,val"
|
||||
|
||||
puts "Looping"
|
||||
for {set idx 1} {$idx < [llength $pin_lines]} {incr idx} {
|
||||
set line [lindex $pin_lines $idx]
|
||||
puts "$line"
|
||||
|
||||
set site_str [lindex $line 0]
|
||||
set pin_str [lindex $line 1]
|
||||
set io [lindex $line 2]
|
||||
set cell_str [lindex $line 3]
|
||||
# Skip unused site
|
||||
if {"$pin_str" == ""} {
|
||||
continue
|
||||
}
|
||||
|
||||
# Have: site
|
||||
# Want: pin for site
|
||||
set site [get_sites $site_str]
|
||||
set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
|
||||
set port [get_ports $pin_str]
|
||||
set tile [get_tiles -of_objects $site]
|
||||
set pin [dict get $io_pin_sites $site]
|
||||
|
||||
set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" $port
|
||||
|
||||
puts $fp "$port,$site,$tile,$pin"
|
||||
}
|
||||
close $fp
|
||||
}
|
||||
|
||||
proc run {} {
|
||||
create_project -force -part $::env(XRAY_PART) design design
|
||||
read_verilog top.v
|
||||
synth_design -top top
|
||||
|
||||
# Mostly doesn't matter since IOB are special, but add anyway
|
||||
create_pblock roi
|
||||
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
|
||||
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
|
||||
|
||||
loc_pins
|
||||
|
||||
set_property CFGBVS VCCO [current_design]
|
||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||
set_param tcl.collectionResultDisplayLimit 0
|
||||
|
||||
place_design
|
||||
route_design
|
||||
|
||||
write_checkpoint -force design.dcp
|
||||
write_bitstream -force design.bit
|
||||
}
|
||||
|
||||
run
|
||||
|
|
@ -0,0 +1 @@
|
|||
LIOB33.IOB_Y1.MACRO
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
'''
|
||||
Generate a primitive to place at every I/O
|
||||
Unlike CLB tests, the LFSR for this is inside the ROI, not driving it
|
||||
'''
|
||||
|
||||
import os
|
||||
import random
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
from prjxray import util
|
||||
from prjxray import verilog
|
||||
|
||||
|
||||
def gen_iobs():
|
||||
'''
|
||||
IOB33S: main IOB of a diff pair
|
||||
IOB33M: secondary IOB of a diff pair
|
||||
IOB33: not a diff pair. Relatively rare (at least in ROI...2 of them?)
|
||||
Focus on IOB33S to start
|
||||
'''
|
||||
for _tile_name, site_name, site_type in util.get_roi().gen_sites(
|
||||
#['IOB33', 'IOB33S', 'IOB33M']):
|
||||
['IOB33S']):
|
||||
yield site_name, site_type
|
||||
|
||||
|
||||
def write_pins(ports):
|
||||
pinstr = 'site,name,dir,cell\n'
|
||||
for site, (name, dir_, cell) in sorted(ports.items(), key=lambda x: x[1]):
|
||||
# pinstr += 'set_property -dict "PACKAGE_PIN %s IOSTANDARD LVCMOS33" [get_ports %s]' % (packpin, port)
|
||||
pinstr += '%s,%s,%s,%s\n' % (site, name, dir_, cell)
|
||||
open('params.csv', 'w').write(pinstr)
|
||||
|
||||
|
||||
def run():
|
||||
# All possible values
|
||||
iosites = {}
|
||||
for site_name, site_type in gen_iobs():
|
||||
iosites[site_name] = site_type
|
||||
|
||||
# Assigned in this design
|
||||
ports = {}
|
||||
DIN_N = 0
|
||||
DOUT_N = 0
|
||||
|
||||
def remain_sites():
|
||||
return set(iosites.keys()) - set(ports.keys())
|
||||
|
||||
def rand_site():
|
||||
'''Get a random, unused site'''
|
||||
return random.choice(list(remain_sites()))
|
||||
|
||||
def assign_i(site, name):
|
||||
nonlocal DIN_N
|
||||
|
||||
assert site not in ports
|
||||
cell = "di_bufs[%u].ibuf" % DIN_N
|
||||
DIN_N += 1
|
||||
ports[site] = (name, 'input', cell)
|
||||
|
||||
def assign_o(site, name):
|
||||
nonlocal DOUT_N
|
||||
|
||||
assert site not in ports
|
||||
cell = "do_bufs[%u].obuf" % DOUT_N
|
||||
DOUT_N += 1
|
||||
ports[site] = (name, 'output', cell)
|
||||
|
||||
# Assign at least one di and one do
|
||||
assign_i(rand_site(), 'di[0]')
|
||||
assign_o(rand_site(), 'do[0]')
|
||||
# Now assign the rest randomly
|
||||
while len(remain_sites()):
|
||||
site = rand_site()
|
||||
choice = random.randint(0, 2)
|
||||
if choice == 0:
|
||||
assign_i(site, 'di[%u]' % DIN_N)
|
||||
elif choice == 1:
|
||||
assign_o(site, 'do[%u]' % DOUT_N)
|
||||
# Empty to provide a reference for no instance
|
||||
else:
|
||||
ports[site] = ("", "", "")
|
||||
|
||||
write_pins(ports)
|
||||
|
||||
print(
|
||||
'''
|
||||
`define N_DI %u
|
||||
`define N_DO %u
|
||||
|
||||
module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
||||
genvar i;
|
||||
|
||||
//Instantiate BUFs so we can LOC them
|
||||
|
||||
wire [`N_DI-1:0] di_buf;
|
||||
generate
|
||||
for (i = 0; i < `N_DI; i = i+1) begin:di_bufs
|
||||
IBUF ibuf(.I(di[i]), .O(di_buf[i]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
wire [`N_DO-1:0] do_unbuf;
|
||||
generate
|
||||
for (i = 0; i < `N_DO; i = i+1) begin:do_bufs
|
||||
OBUF obuf(.I(do_unbuf[i]), .O(do[i]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
roi roi(.di(di_buf), .do(do_unbuf));
|
||||
endmodule
|
||||
|
||||
//Arbitrary terminate into LUTs
|
||||
module roi(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
||||
genvar i;
|
||||
|
||||
generate
|
||||
for (i = 0; i < `N_DI; i = i+1) begin:dis
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 #(
|
||||
.INIT(64'h8000_0000_0000_0001)
|
||||
) lut (
|
||||
.I0(di[i]),
|
||||
.I1(di[i]),
|
||||
.I2(di[i]),
|
||||
.I3(di[i]),
|
||||
.I4(di[i]),
|
||||
.I5(di[i]),
|
||||
.O());
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
for (i = 0; i < `N_DO; i = i+1) begin:dos
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 #(
|
||||
.INIT(64'h8000_0000_0000_0001)
|
||||
) lut (
|
||||
.I0(),
|
||||
.I1(),
|
||||
.I2(),
|
||||
.I3(),
|
||||
.I4(),
|
||||
.I5(),
|
||||
.O(do[i]));
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
''' % (DIN_N, DOUT_N))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
|
@ -53,8 +53,8 @@ def add_site_group_zero(segmk, site, prefix, vals, zero_val, val):
|
|||
vals: all possible tag enum vals
|
||||
zero_val: tag value known to have no bits set
|
||||
'''
|
||||
assert zero_val in vals, "Got %s, need %s" % (zero_val, vals)
|
||||
assert val in vals, "Got %s, need %s" % (val, vals)
|
||||
# assert zero_val in vals, "Got %s, need %s" % (zero_val, vals)
|
||||
assert val in vals or val == zero_val, "Got %s, need %s" % (val, vals)
|
||||
|
||||
if val == zero_val:
|
||||
# Zero symbol occured, none of the others did
|
||||
|
|
@ -64,10 +64,11 @@ def add_site_group_zero(segmk, site, prefix, vals, zero_val, val):
|
|||
else:
|
||||
# Only add the occured symbol
|
||||
tag = prefix + val
|
||||
segmk.add_site_tag(site, tag, 1)
|
||||
# And zero so that it has something to solve against
|
||||
tag = prefix + zero_val
|
||||
segmk.add_site_tag(site, tag, 0)
|
||||
segmk.add_site_tag(site, tag, True)
|
||||
if zero_val in vals:
|
||||
# And zero so that it has something to solve against
|
||||
tag = prefix + zero_val
|
||||
segmk.add_site_tag(site, tag, False)
|
||||
|
||||
|
||||
class Segmaker:
|
||||
|
|
|
|||
|
|
@ -103,6 +103,23 @@ def parse_db_line(line):
|
|||
return tag, bits, None
|
||||
|
||||
|
||||
def parse_db_lines(fn):
|
||||
with open(fn, "r") as f:
|
||||
for line in f:
|
||||
yield line, parse_db_line(line)
|
||||
|
||||
|
||||
def write_db_lines(fn, entries):
|
||||
new_lines = []
|
||||
for tag, bits in entries.items():
|
||||
new_line = " ".join([tag] + sorted(bits))
|
||||
new_lines.append(new_line)
|
||||
|
||||
with open(fn, "w") as f:
|
||||
for line in sorted(new_lines):
|
||||
print(line, file=f)
|
||||
|
||||
|
||||
def parse_tagbit(x):
|
||||
# !30_07
|
||||
if x[0] == '!':
|
||||
|
|
@ -186,14 +203,12 @@ def gen_tile_bits(db_root, tilej, strict=False, verbose=False):
|
|||
elif not os.path.exists(fn):
|
||||
continue
|
||||
|
||||
with open(fn, "r") as f:
|
||||
for line in f:
|
||||
tag, bits, mode = parse_db_line(line)
|
||||
assert mode is None
|
||||
for bitstr in bits:
|
||||
# 31_06
|
||||
_bit_inv, (bit_addroff, bit_bitoff) = parse_tagbit(bitstr)
|
||||
yield (baseaddr + bit_addroff, bitbase + bit_bitoff, tag)
|
||||
for line, (tag, bits, mode) in parse_db_lines(fn):
|
||||
assert mode is None
|
||||
for bitstr in bits:
|
||||
# 31_06
|
||||
_bit_inv, (bit_addroff, bit_bitoff) = parse_tagbit(bitstr)
|
||||
yield (baseaddr + bit_addroff, bitbase + bit_bitoff, tag)
|
||||
|
||||
|
||||
def specn():
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
#/usr/bin/env python3
|
||||
|
||||
import sys, os, re
|
||||
from prjxray import util
|
||||
|
||||
|
||||
def index_masks(fn_in, groups_in):
|
||||
"""Return a dictionary with the bits active in each group for the specified list of groups"""
|
||||
# Only analyze the given groups
|
||||
groups = {}
|
||||
for group in groups_in:
|
||||
groups[group] = set()
|
||||
|
||||
# Index bits
|
||||
for line, (tag, bits, mode) in util.parse_db_lines(fn_in):
|
||||
assert not mode, "Unresolved tag: %s" % (line, )
|
||||
prefix = tag[0:tag.rfind(".")]
|
||||
group = groups.get(prefix, None)
|
||||
# Drop groups we aren't interested in
|
||||
if group is None:
|
||||
continue
|
||||
for bit in bits:
|
||||
bit = bit.replace("!", "")
|
||||
group.add(bit)
|
||||
|
||||
# Verify we were able to find all groups
|
||||
for groupk, groupv in groups.items():
|
||||
assert len(groupv), "Bad group %s" % groupk
|
||||
|
||||
return groups
|
||||
|
||||
|
||||
def apply_masks(fn_in, groups):
|
||||
"""Add 0 entries ("!") to .db entries based on groups definition"""
|
||||
new_db = {}
|
||||
for line, (tag, bits, mode) in util.parse_db_lines(fn_in):
|
||||
assert not mode, "Unresolved tag: %s" % (line, )
|
||||
prefix = tag[0:tag.rfind(".")]
|
||||
group = groups.get(prefix, None)
|
||||
if group:
|
||||
bits = set(bits)
|
||||
for bit in group:
|
||||
if bit not in bits:
|
||||
bits.add("!" + bit)
|
||||
bits = frozenset(bits)
|
||||
new_db[tag] = bits
|
||||
return new_db
|
||||
|
||||
|
||||
def load_groups(fn):
|
||||
ret = []
|
||||
for l in open(fn, "r"):
|
||||
ret.append(l.strip())
|
||||
return ret
|
||||
|
||||
|
||||
def run(fn_in, fn_out, groups_fn, verbose=False):
|
||||
groups_in = load_groups(groups_fn)
|
||||
groups = index_masks(fn_in, groups_in)
|
||||
new_db = apply_masks(fn_in, groups)
|
||||
util.write_db_lines(fn_out, new_db)
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Create multi-bit entries')
|
||||
parser.add_argument('--verbose', action='store_true', help='')
|
||||
parser.add_argument(
|
||||
'--groups-fn',
|
||||
default="groups.grp",
|
||||
help='File containing one group per line to parse')
|
||||
parser.add_argument('fn_in', help='')
|
||||
parser.add_argument('fn_out', help='')
|
||||
args = parser.parse_args()
|
||||
|
||||
run(args.fn_in, args.fn_out, args.groups_fn, verbose=args.verbose)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys, re
|
||||
import os
|
||||
from prjxray import util
|
||||
|
||||
|
||||
def run(fn_ins, fn_out, strict=False, verbose=False):
|
||||
# tag to bits
|
||||
entries = {}
|
||||
# tag to (bits, line)
|
||||
tags = dict()
|
||||
# bits to (tag, line)
|
||||
bitss = dict()
|
||||
|
||||
for fn_in in fn_ins:
|
||||
for line, (tag, bits, mode) in util.parse_db_lines(fn_in):
|
||||
line = line.strip()
|
||||
assert mode is not None or mode != "always", "strict: got ill defined line: %s" % (
|
||||
line, )
|
||||
|
||||
if tag in tags:
|
||||
orig_bits, orig_line = tags[tag]
|
||||
if orig_bits != bits:
|
||||
print("WARNING: got duplicate tag %s" % (tag, ))
|
||||
print(" Orig line: %s" % orig_line)
|
||||
print(" New line : %s" % line)
|
||||
assert not strict, "strict: got duplicate tag"
|
||||
if bits in bitss:
|
||||
orig_tag, orig_line = bitss[bits]
|
||||
if orig_tag != tag:
|
||||
print("WARNING: got duplicate bits %s" % (bits, ))
|
||||
print(" Orig line: %s" % orig_line)
|
||||
print(" New line : %s" % line)
|
||||
assert not strict, "strict: got duplicate bits"
|
||||
|
||||
entries[tag] = bits
|
||||
tags[tag] = (bits, line)
|
||||
if bits != None:
|
||||
bitss[bits] = (tag, line)
|
||||
|
||||
util.write_db_lines(fn_out, entries)
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Combine multiple .db files")
|
||||
|
||||
util.db_root_arg(parser)
|
||||
parser.add_argument('--verbose', action='store_true', help='')
|
||||
parser.add_argument('--out', help='')
|
||||
parser.add_argument('ins', nargs='+', help='Last takes precedence')
|
||||
args = parser.parse_args()
|
||||
|
||||
run(
|
||||
args.ins,
|
||||
args.out,
|
||||
strict=int(os.getenv("MERGEDB_STRICT", "1")),
|
||||
verbose=args.verbose)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -29,6 +29,7 @@ ${XRAY_PARSEDB} --strict "$2"
|
|||
# However, expand back to L/R to make downstream tools not depend on this
|
||||
# in case we later find exceptions
|
||||
|
||||
ismask=false
|
||||
case "$1" in
|
||||
clbll_l)
|
||||
sed < "$2" > "$tmp1" \
|
||||
|
|
@ -77,6 +78,7 @@ case "$1" in
|
|||
|
||||
mask_*)
|
||||
db=$XRAY_DATABASE_DIR/$XRAY_DATABASE/$1.db
|
||||
ismask=true
|
||||
cp "$2" "$tmp1" ;;
|
||||
|
||||
*)
|
||||
|
|
@ -86,7 +88,12 @@ case "$1" in
|
|||
esac
|
||||
|
||||
touch "$db"
|
||||
sort -u "$tmp1" "$db" | grep -v '<.*>' > "$tmp2" || true
|
||||
if $ismask ; then
|
||||
sort -u "$tmp1" "$db" | grep -v '<.*>' > "$tmp2" || true
|
||||
else
|
||||
# tmp1 must be placed second to take precedence over old bad entries
|
||||
python3 ${XRAY_DIR}/utils/mergedb.py --out "$tmp2" "$db" "$tmp1"
|
||||
fi
|
||||
# Check aggregate db for consistency and make canonical
|
||||
${XRAY_PARSEDB} --strict "$tmp2" "$db"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue