Merge pull request #41 from kc8apf/code_format

Specify and enforce code style for C++ and Python
This commit is contained in:
Rick Altherr 2018-01-09 11:40:57 -08:00 committed by GitHub
commit 17985d1934
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
90 changed files with 1513 additions and 1213 deletions

5
.clang-format Normal file
View File

@ -0,0 +1,5 @@
---
Language: Cpp
BasedOnStyle: Chromium
IndentWidth: 8
UseTab: ForIndentation

View File

@ -2,24 +2,32 @@ language: cpp
matrix:
include:
# Job 1) Test C++ w/ GCC
- os: linux
dist: trusty
compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
env:
- MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
before_install:
- eval "${MATRIX_EVAL}"
script:
- mkdir -p build
- cd build
- cmake -DPRJXRAY_BUILD_TESTING=ON ..
- make -j 4
- ctest
script:
- export CC=gcc-6
- export CXX=g++-6
- mkdir -p build
- pushd build
- cmake -DPRJXRAY_BUILD_TESTING=ON ..
- make -j 4
- ctest
# Job 2) Lint checks on Python and C++
- os: linux
dist: trusty
addons:
apt:
packages:
- clang-format-3.9
install:
- pip install --user -r requirements.txt
script:
- make format
- test $(git status --porcelain | wc -l) -eq 0 || { git diff; false; }

View File

@ -1,7 +1,13 @@
JOBS ?= $(shell nproc)
JOBS ?= 2
CLANG_FORMAT ?= clang-format
go:
git submodule update --init --recursive
mkdir -p build
cd build; cmake ..; make -j$(JOBS)
format:
find . -name \*.cc -and -not -path './third_party/*' -exec $(CLANG_FORMAT) -style=file -i {} \;
find . -name \*.h -and -not -path './third_party/*' -exec $(CLANG_FORMAT) -style=file -i {} \;
find . -name \*.py -and -not -path './third_party/*' -exec autopep8 -i {} \;

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -19,4 +20,3 @@ with open("design.txt", "r") as f:
segmk.compile()
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, json, re
import os
import json
import re
#################################################
# Loading Raw Source Data
@ -55,7 +57,8 @@ with open("carrydata.txt", "r") as f:
for i, n in enumerate("CYINIT:ZRO:ONE:AX:CIN DI0:AX:O5 DI1:AX:O5 DI2:AX:O5 DI3:AX:O5".split()):
n = n.split(":")
for k in n[1:]:
carry[line[0]]["CARRY_%s_MUX_%s" % (n[0], k)] = line[1+i].upper() == k
carry[line[0]]["CARRY_%s_MUX_%s" %
(n[0], k)] = line[1 + i].upper() == k
#################################################
@ -74,10 +77,11 @@ for tilename, tiledata in grid["tiles"].items():
if not found_data:
continue
segname = "%s_%02x" % (tiledata["cfgcol"]["BASE_FRAMEID"][2:], min(tiledata["cfgcol"]["WORDS"]))
segname = "%s_%02x" % (
tiledata["cfgcol"]["BASE_FRAMEID"][2:], min(tiledata["cfgcol"]["WORDS"]))
if not segname in segments:
segments[segname] = { "bits": list(), "tags": dict() }
segments[segname] = {"bits": list(), "tags": dict()}
for site in tiledata["sites"]:
if site not in luts and site not in carry:
@ -98,12 +102,14 @@ for tilename, tiledata in grid["tiles"].items():
if re.match("^CLBL[LM]_[LR]", tile_type) and "LUT.INIT" in name:
tile_type = "CLBLX_X"
segments[segname]["tags"]["%s.%s.%s" % (tile_type, sitekey, name)] = value
segments[segname]["tags"]["%s.%s.%s" %
(tile_type, sitekey, name)] = value
if site in carry:
for name, value in carry[site].items():
tile_type = tiledata["props"]["TYPE"]
segments[segname]["tags"]["%s.%s.%s" % (tile_type, sitekey, name)] = value
segments[segname]["tags"]["%s.%s.%s" %
(tile_type, sitekey, name)] = value
base_frame = int(tiledata["cfgcol"]["BASE_FRAMEID"][2:], 16)
for wordidx in tiledata["cfgcol"]["WORDS"]:
@ -112,7 +118,8 @@ for tilename, tiledata in grid["tiles"].items():
if wordidx not in bits[base_frame]:
continue
for bit_frame, bit_wordidx, bit_bitidx in bits[base_frame][wordidx]:
segments[segname]["bits"].append("%02x_%02x_%02x" % (bit_frame - base_frame, bit_wordidx - min(tiledata["cfgcol"]["WORDS"]), bit_bitidx))
segments[segname]["bits"].append("%02x_%02x_%02x" % (
bit_frame - base_frame, bit_wordidx - min(tiledata["cfgcol"]["WORDS"]), bit_bitidx))
segments[segname]["bits"].sort()
@ -129,4 +136,3 @@ with open("segdata.txt", "w") as f:
print("bit %s" % bitname, file=f)
for tagname, tagval in sorted(segdata["tags"].items()):
print("tag %s %d" % (tagname, tagval), file=f)

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -60,4 +62,3 @@ for tile, pips_srcs_dsts in tiledata.items():
segmk.compile()
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
if line.endswith(".GND_WIRE") or line.endswith(".VCC_WIRE"):
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -8,6 +9,7 @@ from segmaker import segmaker
pipdata = dict()
ignpip = set()
def handle_design(prefix, second_pass):
segmk = segmaker(prefix + ".bits")
@ -73,6 +75,7 @@ def handle_design(prefix, second_pass):
segmk.compile()
segmk.write(prefix[7:])
for arg in sys.argv[1:]:
prefix = arg[0:-4]
handle_design(prefix, False)
@ -80,4 +83,3 @@ for arg in sys.argv[1:]:
for arg in sys.argv[1:]:
prefix = arg[0:-4]
handle_design(prefix, True)

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -21,6 +23,8 @@ def maketodo(pipfile, dbfile):
continue
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,9 @@
#!/usr/bin/env python3
import os, sys, json, re
import os
import sys
import json
import re
#######################################
@ -18,7 +21,7 @@ for arg in sys.argv[1:]:
with open(arg) as f:
line = f.read().strip()
site = arg[7:-6]
frame = int(line[5:5+8], 16)
frame = int(line[5:5 + 8], 16)
site_baseaddr[site] = "0x%08x" % (frame & ~0x7f)
@ -45,7 +48,7 @@ for record in tiles:
if len(record) > 4:
for i in range(4, len(record), 2):
site_type, site_name = record[i:i+2]
site_type, site_name = record[i:i + 2]
if site_name in site_baseaddr:
framebaseaddr = site_baseaddr[site_name]
database["tiles"][tile_name]["sites"][site_name] = site_type
@ -64,15 +67,16 @@ for tile_name, tile_data in database["tiles"].items():
if tile_type in ["CLBLL_L", "CLBLL_R", "CLBLM_L", "CLBLM_R"]:
if tile_type in ["CLBLL_L", "CLBLM_L"]:
int_tile_name = tiles_by_grid[(grid_x+1, grid_y)]
int_tile_name = tiles_by_grid[(grid_x + 1, grid_y)]
else:
int_tile_name = tiles_by_grid[(grid_x-1, grid_y)]
int_tile_name = tiles_by_grid[(grid_x - 1, grid_y)]
segment_name = "SEG_" + tile_name
segtype = tile_type.lower()
database["segments"][segment_name] = dict()
database["segments"][segment_name]["tiles"] = [tile_name, int_tile_name]
database["segments"][segment_name]["tiles"] = [
tile_name, int_tile_name]
database["segments"][segment_name]["type"] = segtype
database["segments"][segment_name]["frames"] = 36
database["segments"][segment_name]["words"] = 2
@ -97,11 +101,11 @@ for tile_name, tile_data in database["tiles"].items():
if tile_type in ["BRAM_L", "DSP_L", "BRAM_R", "DSP_R"]:
for k in range(5):
if tile_type in ["BRAM_L", "DSP_L"]:
interface_tile_name = tiles_by_grid[(grid_x+1, grid_y-k)]
int_tile_name = tiles_by_grid[(grid_x+2, grid_y-k)]
interface_tile_name = tiles_by_grid[(grid_x + 1, grid_y - k)]
int_tile_name = tiles_by_grid[(grid_x + 2, grid_y - k)]
else:
interface_tile_name = tiles_by_grid[(grid_x-1, grid_y-k)]
int_tile_name = tiles_by_grid[(grid_x-2, grid_y-k)]
interface_tile_name = tiles_by_grid[(grid_x - 1, grid_y - k)]
int_tile_name = tiles_by_grid[(grid_x - 2, grid_y - k)]
segment_name = "SEG_" + tile_name.replace("_", "%d_" % k, 1)
segtype = tile_type.lower().replace("_", "%d_" % k, 1)
@ -112,12 +116,14 @@ for tile_name, tile_data in database["tiles"].items():
database["segments"][segment_name]["words"] = 2
if k == 0:
database["segments"][segment_name]["tiles"] = [tile_name, interface_tile_name, int_tile_name]
database["segments"][segment_name]["tiles"] = [
tile_name, interface_tile_name, int_tile_name]
database["tiles"][tile_name]["segment"] = segment_name
database["tiles"][interface_tile_name]["segment"] = segment_name
database["tiles"][int_tile_name]["segment"] = segment_name
else:
database["segments"][segment_name]["tiles"] = [interface_tile_name, int_tile_name]
database["segments"][segment_name]["tiles"] = [
interface_tile_name, int_tile_name]
database["tiles"][interface_tile_name]["segment"] = segment_name
database["tiles"][int_tile_name]["segment"] = segment_name
@ -128,7 +134,8 @@ for tile_name, tile_data in database["tiles"].items():
for segment_name in database["segments"].keys():
if "baseaddr" in database["segments"][segment_name]:
framebase, wordbase = database["segments"][segment_name]["baseaddr"]
inttile = [tile for tile in database["segments"][segment_name]["tiles"] if database["tiles"][tile]["type"] in ["INT_L", "INT_R"]][0]
inttile = [tile for tile in database["segments"][segment_name]["tiles"]
if database["tiles"][tile]["type"] in ["INT_L", "INT_R"]][0]
grid_x = database["tiles"][inttile]["grid_x"]
grid_y = database["tiles"][inttile]["grid_y"]
@ -156,7 +163,8 @@ for segment_name in database["segments"].keys():
seg = database["tiles"][tile]["segment"]
if "baseaddr" in database["segments"][seg]:
assert database["segments"][seg]["baseaddr"] == [framebase, wordbase]
assert database["segments"][seg]["baseaddr"] == [
framebase, wordbase]
else:
database["segments"][seg]["baseaddr"] = [framebase, wordbase]
@ -172,7 +180,8 @@ for segment_name in database["segments"].keys():
for segment_name in start_segments:
framebase, wordbase = database["segments"][segment_name]["baseaddr"]
inttile = [tile for tile in database["segments"][segment_name]["tiles"] if database["tiles"][tile]["type"] in ["INT_L", "INT_R"]][0]
inttile = [tile for tile in database["segments"][segment_name]["tiles"]
if database["tiles"][tile]["type"] in ["INT_L", "INT_R"]][0]
grid_x = database["tiles"][inttile]["grid_x"]
grid_y = database["tiles"][inttile]["grid_y"]
@ -192,4 +201,3 @@ for segment_name in start_segments:
# Write
print(json.dumps(database, sort_keys=True, indent="\t"))

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -22,4 +23,3 @@ with open("design_%s.txt" % sys.argv[1], "r") as f:
segmk.compile()
segmk.write(sys.argv[1])

View File

@ -11,22 +11,25 @@ LDPE Primitive: Transparent Data Latch with Asynchronous Preset and Gate Enable
from prims import *
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
segmk = segmaker("design.bits")
def ones(l):
#return l + [x + '_1' for x in l]
#return sorted(l + [x + '_1' for x in l])
# return l + [x + '_1' for x in l]
# return sorted(l + [x + '_1' for x in l])
ret = []
for x in l:
ret.append(x)
ret.append(x + '_1')
return ret
def loadtop():
'''
i,prim,loc,bel
@ -39,17 +42,20 @@ def loadtop():
f.readline()
ret = {}
for l in f:
i,prim,loc,bel,init = l.split(",")
i, prim, loc, bel, init = l.split(",")
i = int(i)
init = int(init)
ret[loc] = (i,prim,loc,bel,init)
ret[loc] = (i, prim, loc, bel, init)
return ret
top = loadtop()
def vs2i(s):
return {"1'b0": 0, "1'b1": 1}[s]
print("Loading tags from design.txt")
with open("design.txt", "r") as f:
for line in f:
@ -99,7 +105,7 @@ with open("design.txt", "r") as f:
# Synchronous vs asynchronous FF
# Unlike most bits, shared between all CLB FFs
segmk.addtag(site, "FFSYNC",
cel_prim in ('FDSE', 'FDRE'))
cel_prim in ('FDSE', 'FDRE'))
# Latch bit
# Only applies to LUT6 (non-5) FF's
@ -113,8 +119,7 @@ with open("design.txt", "r") as f:
Z => inversion
'''
segmk.addtag(site, "%s.ZRST" % ff_name,
cel_prim in ('FDRE', 'FDCE', 'LDCE'))
cel_prim in ('FDRE', 'FDCE', 'LDCE'))
segmk.compile()
segmk.write()

View File

@ -1,64 +1,67 @@
def ones(l):
#return l + [x + '_1' for x in l]
#return sorted(l + [x + '_1' for x in l])
# return l + [x + '_1' for x in l]
# return sorted(l + [x + '_1' for x in l])
ret = []
for x in l:
ret.append(x)
ret.append(x + '_1')
return ret
# The complete primitive sets
ffprims_fall = ones([
'FD',
'FDC',
'FDCE',
'FDE',
'FDP',
'FDPE',
'FDR',
'FDRE',
'FDS',
'FDSE',
])
'FD',
'FDC',
'FDCE',
'FDE',
'FDP',
'FDPE',
'FDR',
'FDRE',
'FDS',
'FDSE',
])
ffprims_lall = ones([
'LDC',
'LDCE',
'LDE',
'LDPE',
'LDP',
])
'LDC',
'LDCE',
'LDE',
'LDPE',
'LDP',
])
# Base primitives
ffprims_f = [
'FDRE',
'FDSE',
'FDCE',
'FDPE',
]
'FDRE',
'FDSE',
'FDCE',
'FDPE',
]
ffprims_l = [
'LDCE',
'LDPE',
]
'LDCE',
'LDPE',
]
ffprims = ffprims_f + ffprims_l
def isff(prim):
return prim.startswith("FD")
def isl(prim):
return prim.startswith("LD")
ff_bels_5 = [
'A5FF',
'B5FF',
'C5FF',
'D5FF',
]
'A5FF',
'B5FF',
'C5FF',
'D5FF',
]
ff_bels_ffl = [
'AFF',
'BFF',
'CFF',
'DFF',
]
'AFF',
'BFF',
'CFF',
'DFF',
]
ff_bels = ff_bels_ffl + ff_bels_5
#ff_bels = ff_bels_ffl

View File

@ -5,14 +5,17 @@ import re
from prims import *
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 600
SLICEX, SLICEY = slice_xy()
# 800
@ -25,11 +28,13 @@ print('//Requested CLBs: %s' % str(CLBN))
f = open("top.txt", "w")
f.write("i,prim,loc,bel,init\n")
def gen_slices():
for slicey in range(*SLICEY):
for slicex in range(*SLICEX):
yield "SLICE_X%dY%d" % (slicex, slicey)
DIN_N = CLBN * 4
DOUT_N = CLBN * 1
@ -64,7 +69,8 @@ endmodule
''' % (DIN_N, DOUT_N))
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
ffprim = random.choice(ones(ffprims))
# clb_FD clb_FD (.clk(clk), .din(din[ 0 +: 4]), .dout(dout[ 0]));
@ -79,7 +85,8 @@ for i in range(CLBN):
#bel = "AFF"
print(' clb_%s' % ffprim)
print(' #(.LOC("%s"), .BEL("%s"), .INIT(%d))' % (loc, bel, init))
print(' clb_%d (.clk(clk), .din(din[ %d +: 4]), .dout(dout[ %d]));' % (i, 4 * i, 1 * i))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 4]), .dout(dout[ %d]));' % (i, 4 * i, 1 * i))
f.write("%d,%s,%s,%s,%d\n" % (i, ffprim, loc, bel, init))
print('''endmodule
@ -488,4 +495,3 @@ module clb_LDPE_1 (input clk, input [3:0] din, output dout);
endmodule
''')

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -17,7 +18,7 @@ clb_N5FFMUX,SLICE_X14Y100,3,1
f = open('params.csv', 'r')
f.readline()
for l in f:
module,loc,n,def_a = l.split(',')
module, loc, n, def_a = l.split(',')
def_a = int(def_a)
n = int(n)
#which = chr(ord('A') + n)
@ -30,4 +31,3 @@ for l in f:
segmk.addtag(loc, "%c5FF.MUX.B" % which, 1 ^ def_a ^ inv)
segmk.compile()
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 40
SLICEX, SLICEY = slice_xy()
# 800
@ -20,11 +23,13 @@ print('//SLICEY: %s' % str(SLICEY))
print('//SLICEN: %s' % str(SLICEN))
print('//Requested CLBs: %s' % str(CLBN))
def gen_slices():
for slicey in range(*SLICEY):
for slicex in range(*SLICEX):
yield "SLICE_X%dY%d" % (slicex, slicey)
DIN_N = CLBN * 8
DOUT_N = CLBN * 8
@ -61,7 +66,8 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,n,def_a\n')
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
bel = ''
@ -72,7 +78,8 @@ for i in range(CLBN):
print(' %s' % module)
print(' #(.LOC("%s"), .N(%d), .DEF_A(%d))' % (loc, n, def_a))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
f.write('%s,%s,%s,%s\n' % (module, loc, n, def_a))
f.close()
@ -203,4 +210,3 @@ module clb_N5FFMUX (input clk, input [7:0] din, output [7:0] dout);
.D(ffds[0]));
endmodule
''')

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -17,7 +18,7 @@ clb_NCY0_O5,SLICE_X17Y100,A6LUT,2
f = open('params.csv', 'r')
f.readline()
for l in f:
module,loc,bel,n = l.split(',')
module, loc, bel, n = l.split(',')
n = int(n)
# A, B, etc
which = bel[0]
@ -26,4 +27,3 @@ for l in f:
segmk.addtag(loc, "CARRY4.%cCY0" % which, module == 'clb_NCY0_O5')
segmk.compile()
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 400
SLICEX, SLICEY = slice_xy()
# 800
@ -20,11 +23,13 @@ print('//SLICEY: %s' % str(SLICEY))
print('//SLICEN: %s' % str(SLICEN))
print('//Requested CLBs: %s' % str(CLBN))
def gen_slices():
for slicey in range(*SLICEY):
for slicex in range(*SLICEX):
yield "SLICE_X%dY%d" % (slicex, slicey)
DIN_N = CLBN * 8
DOUT_N = CLBN * 8
@ -63,7 +68,8 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,bel,n\n')
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
bel = ''
@ -77,7 +83,8 @@ for i in range(CLBN):
print(' %s' % module)
print(' #(.LOC("%s"), .BEL("%s"), .N(%d))' % (loc, bel, n))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
f.write('%s,%s,%s,%s\n' % (module, loc, bel, n))
f.close()
@ -156,4 +163,3 @@ module clb_NCY0_O5 (input clk, input [7:0] din, output [7:0] dout);
CARRY4 carry4(.O(o), .CO(), .DI(di), .S(s), .CYINIT(1'b0), .CI());
endmodule
''')

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -17,7 +18,7 @@ clb_FDRE,SLICE_X14Y100,1,1
f = open('params.csv', 'r')
f.readline()
for l in f:
name,site,ce,r = l.split(',')
name, site, ce, r = l.split(',')
ce = int(ce)
r = int(r)
@ -30,4 +31,3 @@ for l in f:
segmk.addtag(site, "SRUSEDMUX", r)
segmk.compile()
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 600
SLICEX, SLICEY = slice_xy()
# 800
@ -20,26 +23,28 @@ print('//SLICEY: %s' % str(SLICEY))
print('//SLICEN: %s' % str(SLICEN))
print('//Requested CLBs: %s' % str(CLBN))
def gen_slices():
for slicey in range(*SLICEY):
for slicex in range(*SLICEX):
yield "SLICE_X%dY%d" % (slicex, slicey)
DIN_N = CLBN * 4
DOUT_N = CLBN * 1
ffprims = (
'FDRE',
'FDRE',
)
ff_bels = (
'AFF',
'A5FF',
'BFF',
'B5FF',
'CFF',
'C5FF',
'DFF',
'D5FF',
)
'AFF',
'A5FF',
'BFF',
'B5FF',
'CFF',
'C5FF',
'DFF',
'D5FF',
)
print('''
module top(input clk, stb, di, output do);
@ -74,7 +79,8 @@ endmodule
f = open('params.csv', 'w')
f.write('name,loc,ce,r\n')
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
ffprim = random.choice(ffprims)
force_ce = random.randint(0, 1)
@ -86,8 +92,10 @@ for i in range(CLBN):
bel = "AFF"
name = 'clb_%s' % ffprim
print(' %s' % name)
print(' #(.LOC("%s"), .BEL("%s"), .FORCE_CE1(%d), .nFORCE_R0(%d))' % (loc, bel, force_ce, force_r))
print(' clb_%d (.clk(clk), .din(din[ %d +: 4]), .dout(dout[ %d]));' % (i, 4 * i, 1 * i))
print(' #(.LOC("%s"), .BEL("%s"), .FORCE_CE1(%d), .nFORCE_R0(%d))' % (
loc, bel, force_ce, force_r))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 4]), .dout(dout[ %d]));' % (i, 4 * i, 1 * i))
f.write('%s,%s,%s,%s\n' % (name, loc, force_ce, force_r))
f.close()
print('''endmodule
@ -112,4 +120,3 @@ module clb_FDRE (input clk, input [3:0] din, output dout);
);
endmodule
''')

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -18,7 +20,7 @@ clb_NFFMUX_O6,SLICE_X14Y100,3
f = open('params.csv', 'r')
f.readline()
for l in f:
module,loc,n = l.split(',')
module, loc, n = l.split(',')
n = int(n)
which = chr(ord('A') + n)
# clb_NFFMUX_AX => AX
@ -63,17 +65,22 @@ for l in f:
for loc, muxes in cache.items():
for which in muxes:
for src in "F7 F8 CY O5 AX XOR O6".split():
if src == "F7" and which not in "AC": continue
if src == "F8" and which not in "B": continue
if src == "AX": src = which + "X"
if src == "F7" and which not in "AC":
continue
if src == "F8" and which not in "B":
continue
if src == "AX":
src = which + "X"
tag = "%sFF.DMUX.%s" % (which, src)
segmk.addtag(loc, tag, 0)
# we know that all bits for those MUXes are in frames 30 and 31, so filter all other bits
def bitfilter(frame_idx, bit_idx):
assert os.getenv("XRAY_DATABASE") == "artix7"
return frame_idx in [30, 31]
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 400
SLICEX, SLICEY = slice_xy()
# 800
@ -20,11 +23,13 @@ print('//SLICEY: %s' % str(SLICEY))
print('//SLICEN: %s' % str(SLICEN))
print('//Requested CLBs: %s' % str(CLBN))
def gen_slices():
for slicey in range(*SLICEY):
for slicex in range(*SLICEX):
yield "SLICE_X%dY%d" % (slicex, slicey)
DIN_N = CLBN * 8
DOUT_N = CLBN * 8
@ -61,9 +66,11 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,n\n')
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
modules = ['clb_NFFMUX_' + x for x in ['AX', 'CY', 'F78', 'O5', 'O6', 'XOR']]
modules = ['clb_NFFMUX_' +
x for x in ['AX', 'CY', 'F78', 'O5', 'O6', 'XOR']]
module = random.choice(modules)
if module == 'clb_NFFMUX_F78':
@ -75,7 +82,8 @@ for i in range(CLBN):
print(' %s' % module)
print(' #(.LOC("%s"), .N(%d))' % (loc, n))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
f.write('%s,%s,%s\n' % (module, loc, n))
f.close()
@ -330,4 +338,3 @@ module clb_NFFMUX_XOR (input clk, input [7:0] din, output [7:0] dout);
.ff_d(caro));
endmodule
''')

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -18,7 +20,7 @@ clb_NFFMUX_O6,SLICE_X14Y100,3
f = open('params.csv', 'r')
f.readline()
for l in f:
module,loc,n = l.split(',')
module, loc, n = l.split(',')
n = int(n)
which = chr(ord('A') + n)
# clb_NFFMUX_AX => AX
@ -63,12 +65,16 @@ for l in f:
for loc, muxes in cache.items():
for which in muxes:
for src in "F7 F8 CY O5 XOR O6 5Q".split():
if src == "F7" and which not in "AC": continue
if src == "F8" and which not in "B": continue
if src == "5Q": src = which + "5Q"
if src == "F7" and which not in "AC":
continue
if src == "F8" and which not in "B":
continue
if src == "5Q":
src = which + "5Q"
tag = "%sMUX.%s" % (which, src)
segmk.addtag(loc, tag, 0)
def bitfilter(frame_idx, bit_idx):
assert os.getenv("XRAY_DATABASE") == "artix7"
@ -76,15 +82,16 @@ def bitfilter(frame_idx, bit_idx):
# in this fuzzer we get some aliasing with those bits, so we have to manually exclude
# them. (Maybe FIXME: read the bit locations from the database files)
if (frame_idx, bit_idx) in [
(30, 55), (31, 55), # D5MA
(31, 44), (31, 45), # C5MA
(30, 19), (31, 19), # B5MA
(30, 9), (31, 8), # A5MA
]: return False
(30, 55), (31, 55), # D5MA
(31, 44), (31, 45), # C5MA
(30, 19), (31, 19), # B5MA
(30, 9), (31, 8), # A5MA
]:
return False
# we know that all bits for those MUXes are in frames 30 and 31, so filter all other bits
return frame_idx in [30, 31]
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 400
SLICEX, SLICEY = slice_xy()
# 800
@ -20,11 +23,13 @@ print('//SLICEY: %s' % str(SLICEY))
print('//SLICEN: %s' % str(SLICEN))
print('//Requested CLBs: %s' % str(CLBN))
def gen_slices():
for slicey in range(*SLICEY):
for slicex in range(*SLICEX):
yield "SLICE_X%dY%d" % (slicex, slicey)
DIN_N = CLBN * 8
DOUT_N = CLBN * 8
@ -61,7 +66,8 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,n\n')
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
# Don't have an O6 example
modules = ['clb_NOUTMUX_' + x for x in ['CY', 'F78', 'O5', 'XOR', 'B5Q']]
@ -76,7 +82,8 @@ for i in range(CLBN):
print(' %s' % module)
print(' #(.LOC("%s"), .N(%d))' % (loc, n))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
f.write('%s,%s,%s\n' % (module, loc, n))
f.close()
@ -305,4 +312,3 @@ module clb_NOUTMUX_B5Q (input clk, input [7:0] din, output [7:0] dout);
.ff_q(dout[0]));
endmodule
''')

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -11,7 +13,7 @@ print("Loading tags")
f = open('params.csv', 'r')
f.readline()
for l in f:
module,loc,loc2 = l.split(',')
module, loc, loc2 = l.split(',')
# clb_PRECYINIT_AX => AX
src = module.replace('clb_PRECYINIT_', '')
@ -29,4 +31,3 @@ for l in f:
segmk.compile()
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 400
SLICEX, SLICEY = slice_xy()
# 800
@ -22,12 +25,15 @@ print('//Requested CLBs: %s' % str(CLBN))
# Rearranged to sweep Y so that carry logic is easy to allocate
# XXX: careful...if odd number of Y in ROI will break carry
def gen_slices():
for slicex in range(*SLICEX):
for slicey in range(*SLICEY):
# caller may reject position if needs more room
yield ("SLICE_X%dY%d" % (slicex, slicey), (slicex, slicey))
DIN_N = CLBN * 8
DOUT_N = CLBN * 8
@ -64,7 +70,8 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,loc2\n')
slices = gen_slices()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
for i in range(CLBN):
# Don't have an O6 example
modules = ['clb_PRECYINIT_' + x for x in ['0', '1', 'AX', 'CIN']]
@ -88,7 +95,8 @@ for i in range(CLBN):
print(' %s' % module)
print(' #(%s)' % (params))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
print(
' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (i, 8 * i, 8 * i))
f.write('%s,%s\n' % (module, paramsc))
f.close()
@ -134,4 +142,3 @@ module clb_PRECYINIT_CIN (input clk, input [7:0] din, output [7:0] dout);
CARRY4 carry4_ci(.O(), .CO(co), .DI(din[3:0]), .S(din[7:4]), .CYINIT(1'b0), .CI());
endmodule
''')

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, re, os
import sys
import re
import os
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -12,12 +14,12 @@ segmk = segmaker("design.bits")
multi_bels_by = [
'SRL16E',
'SRLC32E',
]
]
# Not BELable
multi_bels_bn = [
'RAM32X1S',
'RAM64X1S',
]
]
# Those requiring special resources
# Just make one per module
@ -25,7 +27,7 @@ greedy_modules = [
'my_RAM128X1D',
'my_RAM128X1S',
'my_RAM256X1S',
]
]
print("Loading tags")
'''
@ -38,9 +40,10 @@ f = open('params.csv', 'r')
f.readline()
for l in f:
l = l.strip()
module,loc,p0,p1,p2,p3 = l.split(',')
module, loc, p0, p1, p2, p3 = l.split(',')
segmk.addtag(loc, "WA7USED", module in ('my_RAM128X1D', 'my_RAM128X1S', 'my_RAM256X1S'))
segmk.addtag(loc, "WA7USED", module in (
'my_RAM128X1D', 'my_RAM128X1S', 'my_RAM256X1S'))
segmk.addtag(loc, "WA8USED", module == 'my_RAM256X1S')
# (a, b, c, d)
@ -53,7 +56,7 @@ for l in f:
if module == 'my_ram_N':
# Each one of: SRL16E, SRLC32E, LUT6
bels = [p0,p1,p2,p3]
bels = [p0, p1, p2, p3]
# Clock Enable (CE) clock gate only enabled if we have clocked elements
# A pure LUT6 does not, but everything else should
@ -82,12 +85,12 @@ for l in f:
(1, 0, 0, 1),
(1, 1, 0, 1),
(1, 1, 1, 1),
]
]
# Uses CD first
pack2 = [
(0, 0, 1, 1),
(1, 1, 1, 1),
]
]
# Always use all 4 sites
if module in ('my_RAM32M', 'my_RAM64M', 'my_RAM128X1D', 'my_RAM256X1S'):
@ -108,7 +111,7 @@ for l in f:
assert(ram[3])
if module == 'my_RAM32X1D':
# Occupies CD
# Occupies CD
size[2] = 1
size[3] = 1
elif module == 'my_RAM32M':
@ -125,12 +128,13 @@ for l in f:
# FIXME
module == segmk.addtag(loc, "%sLUT.SMALL" % bel, size[beli])
def bitfilter(frame_idx, bit_idx):
# Hack to remove aliased PIP bits on CE
# We should either mix up routing more or exclude previous DB entries
assert os.getenv("XRAY_DATABASE") == "artix7"
return (frame_idx, bit_idx) not in [(0, 27), (1, 25), (1, 26), (1, 29)]
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -20,14 +20,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 50
SLICEX, SLICEY = slice_xy()
# 800
@ -39,6 +42,8 @@ print('//Requested CLBs: %s' % str(CLBN))
# Rearranged to sweep Y so that carry logic is easy to allocate
# XXX: careful...if odd number of Y in ROI will break carry
def gen_slicems():
'''
SLICEM at the following:
@ -54,7 +59,7 @@ def gen_slicems():
for slicex in (12, 14):
for slicey in range(*SLICEY):
# caller may reject position if needs more room
#yield ("SLICE_X%dY%d" % (slicex, slicey), (slicex, slicey))
# yield ("SLICE_X%dY%d" % (slicex, slicey), (slicex, slicey))
yield "SLICE_X%dY%d" % (slicex, slicey)
@ -94,7 +99,8 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,bela,belb,belc,beld\n')
slices = gen_slicems()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
randluts = 0
for clbi in range(CLBN):
loc = next(slices)
@ -113,7 +119,7 @@ for clbi in range(CLBN):
'SRL16E',
'SRLC32E',
'LUT6',
]
]
bels = []
for beli in range(4):
@ -144,7 +150,7 @@ for clbi in range(CLBN):
('my_RAM128X1S_N', 2, 1),
('my_RAM128X1D', None, 1),
('my_RAM256X1S', None, 1),
]
]
module, nmax, ff_param = random.choice(modules)
@ -165,7 +171,8 @@ for clbi in range(CLBN):
print(' %s' % module)
print(' #(.LOC("%s")%s)' % (loc, params))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (clbi, 8 * clbi, 8 * clbi))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (
clbi, 8 * clbi, 8 * clbi))
f.write('%s,%s%s\n' % (module, loc, cparams))
f.close()
@ -510,4 +517,3 @@ module my_ram_N (input clk, input [7:0] din, output [7:0] dout);
endmodule
''')

View File

@ -5,7 +5,9 @@
# Can we find instance where they are not aliased?
WA7USED = 0
import sys, re, os
import sys
import re
import os
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -23,7 +25,7 @@ f = open('params.csv', 'r')
f.readline()
for l in f:
l = l.strip()
module,loc,c31,b31,a31 = l.split(',')
module, loc, c31, b31, a31 = l.split(',')
c31 = int(c31)
b31 = int(b31)
a31 = int(a31)
@ -33,4 +35,3 @@ for l in f:
segmk.compile()
segmk.write()

View File

@ -3,14 +3,17 @@ random.seed(0)
import os
import re
def slice_xy():
'''Return (X1, X2), (Y1, Y2) from XRAY_ROI, exclusive end (for xrange)'''
# SLICE_X12Y100:SLICE_X27Y149
# Note XRAY_ROI_GRID_* is something else
m = re.match(r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
m = re.match(
r'SLICE_X([0-9]*)Y([0-9]*):SLICE_X([0-9]*)Y([0-9]*)', os.getenv('XRAY_ROI'))
ms = [int(m.group(i + 1)) for i in range(4)]
return ((ms[0], ms[2] + 1), (ms[1], ms[3] + 1))
CLBN = 50
SLICEX, SLICEY = slice_xy()
# 800
@ -22,6 +25,8 @@ print('//Requested CLBs: %s' % str(CLBN))
# Rearranged to sweep Y so that carry logic is easy to allocate
# XXX: careful...if odd number of Y in ROI will break carry
def gen_slicems():
'''
SLICEM at the following:
@ -37,7 +42,7 @@ def gen_slicems():
for slicex in (12, 14):
for slicey in range(*SLICEY):
# caller may reject position if needs more room
#yield ("SLICE_X%dY%d" % (slicex, slicey), (slicex, slicey))
# yield ("SLICE_X%dY%d" % (slicex, slicey), (slicex, slicey))
yield "SLICE_X%dY%d" % (slicex, slicey)
@ -77,7 +82,8 @@ endmodule
f = open('params.csv', 'w')
f.write('module,loc,c31,b31,a31\n')
slices = gen_slicems()
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1))
print('module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (
DIN_N - 1, DOUT_N - 1))
multis = 0
for clbi in range(CLBN):
loc = next(slices)
@ -87,8 +93,10 @@ for clbi in range(CLBN):
a31 = random.randint(0, 1)
print(' %s' % module)
print(' #(.LOC("%s"), .C31(%d), .B31(%d), .A31(%d))' % (loc, c31, b31, a31))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (clbi, 8 * clbi, 8 * clbi))
print(' #(.LOC("%s"), .C31(%d), .B31(%d), .A31(%d))' %
(loc, c31, b31, a31))
print(' clb_%d (.clk(clk), .din(din[ %d +: 8]), .dout(dout[ %d +: 8]));' % (
clbi, 8 * clbi, 8 * clbi))
f.write('%s,%s,%d,%d,%d\n' % (module, loc, c31, b31, a31))
f.close()
@ -159,4 +167,3 @@ module my_NDI1MUX_NI_NMC31 (input clk, input [7:0] din, output [7:0] dout);
.D(lutd[0]));
endmodule
''')

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -63,4 +64,3 @@ for tile, pips_srcs_dsts in tiledata.items():
segmk.compile()
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, re, os
import sys
import re
import os
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -61,12 +63,13 @@ for tile, pips_srcs_dsts in tiledata.items():
elif src_dst[1] not in dsts:
segmk.addtag(tile, "%s.%s" % (dst, src), 0)
def bitfilter(frame_idx, bit_idx):
assert os.getenv("XRAY_DATABASE") in ["artix7", "kintex7"]
if frame_idx in [30, 31]:
return False
return True
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
if re.match(r"^INT_[LR].IMUX(_L)?[0-9]+\.LOGIC_OUTS(_L)?[0-9]+$", line):
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -58,6 +60,7 @@ for tile, pips_srcs_dsts in tiledata.items():
elif src_dst[1] not in dsts:
segmk.addtag(tile, "%s.%s" % (dst, src), 0)
def bitfilter(frame_idx, bit_idx):
assert os.getenv("XRAY_DATABASE") in ["artix7", "kintex7"]
if frame_idx == 0 and bit_idx == 48:
@ -66,6 +69,6 @@ def bitfilter(frame_idx, bit_idx):
return False
return frame_idx in [0, 1]
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
if re.match(r"^INT_[LR].CLK", line):
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -58,12 +60,13 @@ for tile, pips_srcs_dsts in tiledata.items():
elif src_dst[1] not in dsts:
segmk.addtag(tile, "%s.%s" % (dst, src), 0)
def bitfilter(frame_idx, bit_idx):
assert os.getenv("XRAY_DATABASE") in ["artix7", "kintex7"]
if (frame_idx, bit_idx) in [(0, 48), (1, 31), (0, 32), (1, 35)]:
return False
return frame_idx in [0, 1]
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
if re.match(r"^INT_[LR].CTRL", line):
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -60,4 +62,3 @@ for tile, pips_srcs_dsts in tiledata.items():
segmk.compile()
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
if re.match(r"^INT_[LR].GFAN", line) and not line.endswith(".GND_WIRE"):
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -60,4 +62,3 @@ for tile, pips_srcs_dsts in tiledata.items():
segmk.compile()
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -70,4 +72,3 @@ for tile, pips_srcs_dsts in tiledata.items():
segmk.compile()
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
if not line.endswith(".VCC_WIRE"):
print(line)
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("pips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -40,10 +42,11 @@ for tile, pips_nodes in tiledata.items():
elif dst not in nodes and src not in nodes:
segmk.addtag(tile, "%s.%s" % (dst, src), 0)
def bitfilter(frame_idx, bit_idx):
assert os.getenv("XRAY_DATABASE") in ["artix7", "kintex7"]
return frame_idx in [0, 1]
segmk.compile(bitfilter=bitfilter)
segmk.write()

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, re
import os
import re
def maketodo(pipfile, dbfile):
todos = set()
@ -16,6 +18,8 @@ def maketodo(pipfile, dbfile):
for line in todos:
print(line)
maketodo("bipips_int_l.txt", "%s/%s/segbits_int_l.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("bipips_int_r.txt", "%s/%s/segbits_int_r.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("bipips_int_l.txt", "%s/%s/segbits_int_l.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))
maketodo("bipips_int_r.txt", "%s/%s/segbits_int_r.db" %
(os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")))

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import sys, os, re
import sys
import os
import re
sys.path.append("../../../utils/")
from segmaker import segmaker
@ -50,4 +52,3 @@ for arg in sys.argv[1:]:
segmk.compile()
segmk.write(arg)

View File

@ -1,6 +1,9 @@
#!/usr/bin/env python3
import os, sys, json, re
import os
import sys
import json
import re
tilenodes = dict()
grid2tile = dict()
@ -24,38 +27,56 @@ with open("nodewires.txt") as f:
tilenodes[wire_tile] = dict()
tilenodes[wire_tile][node] = wire_name
def filter_pair(type1, type2, wire1, wire2, delta_x, delta_y):
if type1 in ["HCLK_L", "HCLK_R"]:
is_vertical_wire = False
if wire1.startswith("HCLK_S"): is_vertical_wire = True
if wire1.startswith("HCLK_N"): is_vertical_wire = True
if wire1.startswith("HCLK_W"): is_vertical_wire = True
if wire1.startswith("HCLK_E"): is_vertical_wire = True
if wire1.startswith("HCLK_LV"): is_vertical_wire = True
if wire1.startswith("HCLK_BYP"): is_vertical_wire = True
if wire1.startswith("HCLK_FAN"): is_vertical_wire = True
if wire1.startswith("HCLK_LEAF_CLK_"): is_vertical_wire = True
if wire1.startswith("HCLK_S"):
is_vertical_wire = True
if wire1.startswith("HCLK_N"):
is_vertical_wire = True
if wire1.startswith("HCLK_W"):
is_vertical_wire = True
if wire1.startswith("HCLK_E"):
is_vertical_wire = True
if wire1.startswith("HCLK_LV"):
is_vertical_wire = True
if wire1.startswith("HCLK_BYP"):
is_vertical_wire = True
if wire1.startswith("HCLK_FAN"):
is_vertical_wire = True
if wire1.startswith("HCLK_LEAF_CLK_"):
is_vertical_wire = True
is_horizontal_wire = False
if wire1.startswith("HCLK_CK_"): is_horizontal_wire = True
if wire1.startswith("HCLK_INT_"): is_horizontal_wire = True
if wire1.startswith("HCLK_CK_"):
is_horizontal_wire = True
if wire1.startswith("HCLK_INT_"):
is_horizontal_wire = True
assert is_vertical_wire != is_horizontal_wire
if is_vertical_wire and delta_y == 0: return True
if is_horizontal_wire and delta_x == 0: return True
if is_vertical_wire and delta_y == 0:
return True
if is_horizontal_wire and delta_x == 0:
return True
if type1 in ["INT_L", "INT_R"]:
# the wires with underscore after BEG/END all connect vertically
if (("BEG_" in wire1) or ("END_" in wire1)) and delta_y == 0: return True
if (("BEG_" in wire1) or ("END_" in wire1)) and delta_y == 0:
return True
if type1 in ["BRKH_INT", "BRKH_B_TERM_INT", "T_TERM_INT"]:
if delta_y == 0: return True
if delta_y == 0:
return True
return False
def handle_pair(tile1, tile2):
if tile1 not in tilenodes: return
if tile2 not in tilenodes: return
if tile1 not in tilenodes:
return
if tile2 not in tilenodes:
return
tile1data = grid["tiles"][tile1]
tile2data = grid["tiles"][tile2]
@ -66,7 +87,8 @@ def handle_pair(tile1, tile2):
if grid1_xy > grid2_xy:
return handle_pair(tile2, tile1)
key = (tile1data["type"], tile2data["type"], grid2_xy[0] - grid1_xy[0], grid2_xy[1] - grid1_xy[1])
key = (tile1data["type"], tile2data["type"],
grid2_xy[0] - grid1_xy[0], grid2_xy[1] - grid1_xy[1])
wire_pairs = set()
@ -84,9 +106,10 @@ def handle_pair(tile1, tile2):
else:
database[key] &= wire_pairs
for tile, tiledata in grid["tiles"].items():
grid_right_xy = (tiledata["grid_x"]+1, tiledata["grid_y"])
grid_below_xy = (tiledata["grid_x"], tiledata["grid_y"]+1)
grid_right_xy = (tiledata["grid_x"] + 1, tiledata["grid_y"])
grid_below_xy = (tiledata["grid_x"], tiledata["grid_y"] + 1)
if grid_right_xy in grid2tile:
handle_pair(tile, grid2tile[grid_right_xy])
@ -108,4 +131,3 @@ for key in sorted(database.keys()):
print("Writing tileconn.json.")
with open("tileconn.json", "w") as f:
print(json.dumps(json_db, sort_keys=True, indent="\t"), file=f)

View File

@ -13,17 +13,20 @@ db_site_prop = dict()
db_site_tile = dict()
db_site_bit = dict()
def add_tile(tile):
if tile not in db_tiles:
db_tiles.add(tile)
db_tile_prop[tile] = dict()
db_tile_sites[tile] = list()
def add_site(site):
if site not in db_sites:
db_sites.add(site)
db_site_prop[site] = dict()
with open("%s.txt" % sys.argv[1]) as f:
for line in f:
line = line.split()
@ -89,34 +92,36 @@ for site, bit in db_site_bit.items():
for i in range(50):
m = re.match("(.*)Y([0-9]+)", site)
this_site = "%sY%d" % (m.group(1), int(m.group(2))+i)
this_site = "%sY%d" % (m.group(1), int(m.group(2)) + i)
tile = db_site_tile[this_site]
word = bit_word + 2*i
if word >= 50: word += 1
word = bit_word + 2 * i
if word >= 50:
word += 1
entry = dict()
entry["BASE_FRAMEID"] = "0x%08x" % ((bit_type << 23) | (bit_half << 22) | (bit_row << 17) | (bit_col << 7))
entry["BASE_FRAMEID"] = "0x%08x" % ((bit_type << 23) | (
bit_half << 22) | (bit_row << 17) | (bit_col << 7))
entry["FRAME_TYPE"] = bit_type
entry["FRAME_HALF"] = bit_half
entry["FRAME_ROW"] = bit_row
entry["FRAME_COLUMN"] = bit_col
entry["WORDS"] = [word, word+1]
entry["WORDS"] = [word, word + 1]
database["tiles"][tile]["cfgcol"] = entry
if database["tiles"][tile]["props"]["TILE_TYPE"] in ("CLBLL_L", "CLBLM_L"):
col = int(db_tile_prop[tile]["COLUMN"])
row = int(db_tile_prop[tile]["ROW"])
right_tile = loc_to_tile[(col+1, row)]
right_tile = loc_to_tile[(col + 1, row)]
database["tiles"][right_tile]["cfgcol"] = entry
if database["tiles"][tile]["props"]["TILE_TYPE"] in ("CLBLL_R", "CLBLM_R"):
col = int(db_tile_prop[tile]["COLUMN"])
row = int(db_tile_prop[tile]["ROW"])
left_tile = loc_to_tile[(col-1, row)]
left_tile = loc_to_tile[(col - 1, row)]
database["tiles"][left_tile]["cfgcol"] = entry
@ -133,4 +138,3 @@ print("Number of tiles with assigned column: %d" % tile_cfgcol_count)
with open("%s.json" % sys.argv[1], "w") as f:
print(json.dumps(database, sort_keys=True, indent="\t"), file=f)

View File

@ -1,6 +1,9 @@
#!/usr/bin/env python3
import os, sys, json, re
import os
import sys
import json
import re
from io import StringIO
import argparse
@ -37,13 +40,17 @@ else:
def get_setting(name):
return os.getenv(name)
db_dir = os.path.join(get_setting("XRAY_DATABASE_DIR"), get_setting("XRAY_DATABASE"))
db_dir = os.path.join(get_setting("XRAY_DATABASE_DIR"),
get_setting("XRAY_DATABASE"))
def db_open(fn):
filename = os.path.join(db_dir, fn)
if not os.path.exists(filename):
return StringIO("")
return open(os.path.join(db_dir, fn))
def out_open(fn):
out_dir = os.path.join(args.output, get_setting("XRAY_DATABASE"))
os.makedirs(out_dir, exist_ok=True)
@ -51,6 +58,7 @@ def out_open(fn):
print("Writing %s" % fp)
return open(fp, "w")
clb_bitgroups_db = [
# copy&paste from zero_db in dbfixup.py
"00_21 00_22 00_26 01_28|00_25 01_20 01_21 01_24",
@ -84,9 +92,9 @@ hclk_bitgroups_db = [
# groupings for SNWE bits in frames 2..7
for i in range(0, 64, 4):
clb_bitgroups_db.append("02_%02d 03_%02d 05_%02d 06_%02d 07_%02d|05_%02d 03_%02d 04_%02d 04_%02d" %
(i+1, i, i, i, i+1, i+3, i+1, i+1, i+2))
(i + 1, i, i, i, i + 1, i + 3, i + 1, i + 1, i + 2))
clb_bitgroups_db.append("02_%02d 04_%02d 05_%02d 05_%02d 06_%02d|02_%02d 03_%02d 04_%02d 07_%02d" %
(i+2, i, i+1, i+2, i+2, i+3, i+2, i+3, i+3))
(i + 2, i, i + 1, i + 2, i + 2, i + 3, i + 2, i + 3, i + 3))
clb_left_bits = set()
clb_right_bits = set()
@ -108,6 +116,7 @@ for entry in hclk_bitgroups_db:
for bit in b.split():
hclk_right_bits.add(bit)
class UnionFind:
def __init__(self):
self.parents = dict()
@ -152,8 +161,8 @@ with db_open("tilegrid.json") as f:
"tiles": {
"NULL": {
"grid_x": 0,
"grid_y":0,
"type":"NULL",
"grid_y": 0,
"type": "NULL",
}
}
}
@ -228,10 +237,13 @@ grid_range = None
grid_map = dict()
with out_open("index.html") as f:
print("<html><title>X-Ray %s Database</title><body>" % get_setting("XRAY_DATABASE").upper(), file=f)
print("<h3>X-Ray %s Database</h3>" % get_setting("XRAY_DATABASE").upper(), file=f)
print("<html><title>X-Ray %s Database</title><body>" %
get_setting("XRAY_DATABASE").upper(), file=f)
print("<h3>X-Ray %s Database</h3>" %
get_setting("XRAY_DATABASE").upper(), file=f)
print("<p><b>Part: %s<br/>ROI: %s<br/>ROI Frames: %s</b></p>" % (get_setting("XRAY_PART"), get_setting("XRAY_ROI"), get_setting("XRAY_ROI_FRAMES")), file=f)
print("<p><b>Part: %s<br/>ROI: %s<br/>ROI Frames: %s</b></p>" %
(get_setting("XRAY_PART"), get_setting("XRAY_ROI"), get_setting("XRAY_ROI_FRAMES")), file=f)
for tilename, tiledata in grid["tiles"].items():
grid_x = tiledata["grid_x"]
@ -248,25 +260,33 @@ with out_open("index.html") as f:
print("<table border>", file=f)
for grid_y in range(grid_range[1], grid_range[3]+1):
for grid_y in range(grid_range[1], grid_range[3] + 1):
print("<tr>", file=f)
for grid_x in range(grid_range[0], grid_range[2]+1):
for grid_x in range(grid_range[0], grid_range[2] + 1):
tilename = grid_map[(grid_x, grid_y)]
tiledata = grid["tiles"][tilename]
segdata = None
bgcolor = "#aaaaaa"
if tiledata["type"] in ["INT_L", "INT_R"]: bgcolor="#aaaaff"
if tiledata["type"] in ["CLBLL_L", "CLBLL_R"]: bgcolor="#ffffaa"
if tiledata["type"] in ["CLBLM_L", "CLBLM_R"]: bgcolor="#ffaaaa"
if tiledata["type"] in ["HCLK_L", "HCLK_R"]: bgcolor="#aaffaa"
if tiledata["type"] in ["INT_L", "INT_R"]:
bgcolor = "#aaaaff"
if tiledata["type"] in ["CLBLL_L", "CLBLL_R"]:
bgcolor = "#ffffaa"
if tiledata["type"] in ["CLBLM_L", "CLBLM_R"]:
bgcolor = "#ffaaaa"
if tiledata["type"] in ["HCLK_L", "HCLK_R"]:
bgcolor = "#aaffaa"
if tiledata["type"] in ["BRAM_INT_INTERFACE_L", "BRAM_L"]: bgcolor="#aaffff"
if tiledata["type"] in ["BRAM_INT_INTERFACE_R", "BRAM_R"]: bgcolor="#aaffff"
if tiledata["type"] in ["BRAM_INT_INTERFACE_L", "BRAM_L"]:
bgcolor = "#aaffff"
if tiledata["type"] in ["BRAM_INT_INTERFACE_R", "BRAM_R"]:
bgcolor = "#aaffff"
if tiledata["type"] in ["INT_INTERFACE_L", "DSP_L"]: bgcolor="#ffaaff"
if tiledata["type"] in ["INT_INTERFACE_R", "DSP_R"]: bgcolor="#ffaaff"
if tiledata["type"] in ["INT_INTERFACE_L", "DSP_L"]:
bgcolor = "#ffaaff"
if tiledata["type"] in ["INT_INTERFACE_R", "DSP_R"]:
bgcolor = "#ffaaff"
title = [tilename]
@ -282,21 +302,25 @@ with out_open("index.html") as f:
if "segment" in tiledata:
if "baseaddr" in segdata:
title.append("Baseaddr: %s %d" % tuple(segdata["baseaddr"]))
title.append("Baseaddr: %s %d" %
tuple(segdata["baseaddr"]))
else:
print("Warning: no baseaddr in segment %s (via tile %s)." % (tiledata["segment"], tilename))
print("Warning: no baseaddr in segment %s (via tile %s)." %
(tiledata["segment"], tilename))
tilename = tilename.replace("INT_INTERFACE_", "INTF_")
tilename = tilename.replace("_X", "<br/>X")
tilename = tilename.replace("B_TERM", "B<br/>TERM")
print("<td bgcolor=\"%s\" align=\"center\" title=\"%s\"><span style=\"font-size:10px\">" % (bgcolor, "\n".join(title)), file=f)
print("<td bgcolor=\"%s\" align=\"center\" title=\"%s\"><span style=\"font-size:10px\">" %
(bgcolor, "\n".join(title)), file=f)
if "segment" in tiledata:
segtype = segdata["type"].lower()
print("<a style=\"text-decoration: none; color: black\" href=\"seg_%s.html\">%s</a></span></td>" %
(segtype, tilename.replace("_X", "<br/>X")), file=f)
(segtype, tilename.replace("_X", "<br/>X")), file=f)
else:
print("%s</span></td>" % tilename.replace("_X", "<br/>X").replace("B_TERM", "B<br/>TERM"), file=f)
print("%s</span></td>" % tilename.replace("_X",
"<br/>X").replace("B_TERM", "B<br/>TERM"), file=f)
print("</tr>", file=f)
@ -309,12 +333,14 @@ with out_open("index.html") as f:
for segtype in sorted(segbits.keys()):
with out_open("seg_%s.html" % segtype) as f:
print("<html><title>X-Ray %s Database: %s</title><body>" % (get_setting("XRAY_DATABASE").upper(), segtype.upper()), file=f)
print("<html><title>X-Ray %s Database: %s</title><body>" %
(get_setting("XRAY_DATABASE").upper(), segtype.upper()), file=f)
if segtype in ["hclk_l", "hclk_r"]:
print("<h3>X-Ray %s Database: %s Segment</h3>" % (get_setting("XRAY_DATABASE").upper(), segtype.upper()), file=f)
print("<h3>X-Ray %s Database: %s Segment</h3>" %
(get_setting("XRAY_DATABASE").upper(), segtype.upper()), file=f)
else:
print("<h3>X-Ray %s Database: %s Segment (%s Tile + %s Tile)</h3>" % (get_setting("XRAY_DATABASE").upper(), segtype.upper(),
segtype.upper(), re.sub("clbl[lm]|bram[0-4]|dsp[0-4]", "int", segtype).upper()), file=f)
segtype.upper(), re.sub("clbl[lm]|bram[0-4]|dsp[0-4]", "int", segtype).upper()), file=f)
print("""
<script><!--
@ -364,12 +390,14 @@ function oml() {
print("<tr>", file=f)
print("<th width=\"30\"></th>", file=f)
for frameidx in range(segframes[segtype]):
print("<th width=\"30\"><span style=\"font-size:10px\">%d</span></th>" % frameidx, file=f)
print("<th width=\"30\"><span style=\"font-size:10px\">%d</span></th>" %
frameidx, file=f)
print("</tr>", file=f)
for bitidx in range(31 if (segtype in ["hclk_l", "hclk_r"]) else 63, -1, -1):
print("<tr>", file=f)
print("<th align=\"right\"><span style=\"font-size:10px\">%d</span></th>" % bitidx, file=f)
print(
"<th align=\"right\"><span style=\"font-size:10px\">%d</span></th>" % bitidx, file=f)
for frameidx in range(segframes[segtype]):
bit_pos = "%02d_%02d" % (frameidx, bitidx)
bit_name = segbits_r[segtype][bit_pos] if bit_pos in segbits_r[segtype] else None
@ -420,7 +448,8 @@ function oml() {
else:
bgcolor = "#ff0000"
m = re.search(r"\.([ABCD]5?)FF\.([A-Z]+(\.A|\.B)?)$", bit_name)
m = re.search(
r"\.([ABCD]5?)FF\.([A-Z]+(\.A|\.B)?)$", bit_name)
if m:
bgcolor = "#aaffaa"
if m.group(2) == "ZINI":
@ -478,64 +507,64 @@ function oml() {
label = "BUF"
elif bit_pos in routebits[segtype]:
bgcolor = "#0000ff"
label = "R"
for bn in sorted(routebits[segtype][bit_pos]):
if re.match("^INT_[LR].[SNWE][SNWERL]", bn):
if bn[8] == "1":
bgcolor = "#4466bb"
elif bn[8] == "2":
bgcolor = "#aa88ff"
elif bn[6:9] in "SS6 SE6 NN6 NW6".split():
bgcolor = "#7755ff"
else:
bgcolor = "#88aaff"
label = bn[6:9]
elif re.match("^INT_[LR].IMUX", bn):
m = re.match("^INT_[LR].IMUX(_L)?(\d+)", bn)
bgcolor = "#88aaff"
label = "IM" + m.group(2)
elif re.match("^INT_[LR].BYP_ALT", bn):
bgcolor = "#7755ff"
label = "BA" + bn[13]
elif re.match("^INT_[LR].FAN_ALT", bn):
bgcolor = "#0000ff"
label = "R"
for bn in sorted(routebits[segtype][bit_pos]):
if re.match("^INT_[LR].[SNWE][SNWERL]", bn):
if bn[8] == "1":
bgcolor = "#4466bb"
label = "FA" + bn[13]
elif re.match("^INT_[LR].CLK", bn):
bgcolor = "#4466bb"
label = "CLK"
elif re.match("^INT_[LR].CTRL", bn):
bgcolor = "#7755ff"
label = "CTRL"
elif re.match("^INT_[LR].GFAN", bn):
bgcolor = "#7755ff"
label = "GFAN"
elif re.match("^INT_[LR].LVB", bn):
bgcolor = "#88aaff"
label = "LVB"
elif re.match("^INT_[LR].LV", bn):
bgcolor = "#88aaff"
label = "LV"
elif re.match("^INT_[LR].LH", bn):
bgcolor = "#4466bb"
label = "LH"
elif re.match("^CLBL[LM]_[LR].SLICE[LM]_X[01].[ABCD]FF.DMUX", bn):
bgcolor = "#88aaff"
label = "DMX"
elif re.match("^CLBL[LM]_[LR].SLICE[LM]_X[01].[ABCD]MUX", bn):
elif bn[8] == "2":
bgcolor = "#aa88ff"
label = "OMX"
elif re.match("^CLBL[LM]_[LR].SLICE[LM]_X[01].PRECYINIT", bn):
bgcolor = "#88aaff"
label = "CYI"
elif re.match("^HCLK_[LR]", bn) and "_B_BOT" in bn:
bgcolor = "#4466bb"
label = "BOT"
elif re.match("^HCLK_[LR]", bn) and "_B_TOP" in bn:
elif bn[6:9] in "SS6 SE6 NN6 NW6".split():
bgcolor = "#7755ff"
label = "TOP"
piptypes[bit_pos] = label
title.append(bn)
else:
bgcolor = "#88aaff"
label = bn[6:9]
elif re.match("^INT_[LR].IMUX", bn):
m = re.match("^INT_[LR].IMUX(_L)?(\d+)", bn)
bgcolor = "#88aaff"
label = "IM" + m.group(2)
elif re.match("^INT_[LR].BYP_ALT", bn):
bgcolor = "#7755ff"
label = "BA" + bn[13]
elif re.match("^INT_[LR].FAN_ALT", bn):
bgcolor = "#4466bb"
label = "FA" + bn[13]
elif re.match("^INT_[LR].CLK", bn):
bgcolor = "#4466bb"
label = "CLK"
elif re.match("^INT_[LR].CTRL", bn):
bgcolor = "#7755ff"
label = "CTRL"
elif re.match("^INT_[LR].GFAN", bn):
bgcolor = "#7755ff"
label = "GFAN"
elif re.match("^INT_[LR].LVB", bn):
bgcolor = "#88aaff"
label = "LVB"
elif re.match("^INT_[LR].LV", bn):
bgcolor = "#88aaff"
label = "LV"
elif re.match("^INT_[LR].LH", bn):
bgcolor = "#4466bb"
label = "LH"
elif re.match("^CLBL[LM]_[LR].SLICE[LM]_X[01].[ABCD]FF.DMUX", bn):
bgcolor = "#88aaff"
label = "DMX"
elif re.match("^CLBL[LM]_[LR].SLICE[LM]_X[01].[ABCD]MUX", bn):
bgcolor = "#aa88ff"
label = "OMX"
elif re.match("^CLBL[LM]_[LR].SLICE[LM]_X[01].PRECYINIT", bn):
bgcolor = "#88aaff"
label = "CYI"
elif re.match("^HCLK_[LR]", bn) and "_B_BOT" in bn:
bgcolor = "#4466bb"
label = "BOT"
elif re.match("^HCLK_[LR]", bn) and "_B_TOP" in bn:
bgcolor = "#7755ff"
label = "TOP"
piptypes[bit_pos] = label
title.append(bn)
if label is None:
label = "&nbsp;"
@ -552,7 +581,7 @@ function oml() {
known_bits += 1
print("<td id=\"bit%s\" onmouseenter=\"ome('%s');\" onmouseleave=\"oml();\" bgcolor=\"%s\" align=\"center\" title=\"%s\"%s><span style=\"font-size:10px\">%s</span></td>" %
(bit_pos, bit_pos, bgcolor, "\n".join(title), onclick, label), file=f)
(bit_pos, bit_pos, bgcolor, "\n".join(title), onclick, label), file=f)
print("</tr>", file=f)
print("</table>", file=f)
@ -562,9 +591,9 @@ function oml() {
if True:
print(" unused: %d, unknown: %d, known: %d, total: %d, percentage: %.2f%% (%.2f%%)" % (
unused_bits, unknown_bits, known_bits, unused_bits + unknown_bits + known_bits,
100 * known_bits / (unknown_bits + unused_bits + known_bits),
100 * (known_bits + unused_bits) / (unknown_bits + unused_bits + known_bits)))
unused_bits, unknown_bits, known_bits, unused_bits + unknown_bits + known_bits,
100 * known_bits / (unknown_bits + unused_bits + known_bits),
100 * (known_bits + unused_bits) / (unknown_bits + unused_bits + known_bits)))
bits_by_prefix = dict()
@ -583,12 +612,14 @@ function oml() {
print("<p/>", file=f)
print("<h4>%s</h4>" % prefix, file=f)
print("<table cellspacing=0>", file=f)
print("<tr><th width=\"400\" align=\"left\">Bit Name</th><th>Position</th></tr>", file=f)
print(
"<tr><th width=\"400\" align=\"left\">Bit Name</th><th>Position</th></tr>", file=f)
trstyle = ""
for bit_name, bit_pos in sorted(bits):
trstyle = " bgcolor=\"#dddddd\"" if trstyle == "" else ""
print("<tr%s><td>%s</td><td>%s</td></tr>" % (trstyle, bit_name, bit_pos), file=f)
print("<tr%s><td>%s</td><td>%s</td></tr>" %
(trstyle, bit_name, bit_pos), file=f)
print("</table>", file=f)
@ -663,7 +694,8 @@ function oml() {
print("<a id=\"b%s\"/>" % bit, file=f)
print("<script><!--", file=f)
print("grp2bits['%s'] = ['%s'];" % (grp_bits[0], "', '".join(grp_bits)), file=f)
print("grp2bits['%s'] = ['%s'];" %
(grp_bits[0], "', '".join(grp_bits)), file=f)
for bit in grp_bits:
print("bit2grp['%s'] = '%s';" % (bit, grp_bits[0]), file=f)
print("//--></script>", file=f)
@ -682,8 +714,10 @@ function oml() {
line = " --><td>%s</td>" % (pip)
for bit in grp_bits:
c = "-"
if bit in routebits[segtype] and pip in routebits[segtype][bit]: c = "1"
if bit in routezbits[segtype] and pip in routezbits[segtype][bit]: c = "0"
if bit in routebits[segtype] and pip in routebits[segtype][bit]:
c = "1"
if bit in routezbits[segtype] and pip in routezbits[segtype][bit]:
c = "0"
line = "%s%s<td align=\"center\">%s</td>" % (c, line, c)
lines.append(line)
@ -699,8 +733,10 @@ function oml() {
if len(shared_bits[bit]) > 1:
if first_note:
print("<p><b>Note(s):</b><br/>", file=f)
print("Warning: Groups sharing bit %s: %s." % (bit, ", ".join(sorted(shared_bits[bit]))))
print("Groups sharing bit <b>%s</b>: %s.<br/>" % (bit, ", ".join(sorted(shared_bits[bit]))), file=f)
print("Warning: Groups sharing bit %s: %s." %
(bit, ", ".join(sorted(shared_bits[bit]))))
print("Groups sharing bit <b>%s</b>: %s.<br/>" %
(bit, ", ".join(sorted(shared_bits[bit]))), file=f)
first_note = False
if not first_note:
print("</p>", file=f)
@ -708,13 +744,15 @@ function oml() {
for tile_type in segtiles[segtype]:
print("<h3>Tile %s Pseudo PIPs</h3>" % tile_type, file=f)
print("<table cellspacing=0>", file=f)
print("<tr><th width=\"500\" align=\"left\">PIP</th><th>Type</th></tr>", file=f)
print(
"<tr><th width=\"500\" align=\"left\">PIP</th><th>Type</th></tr>", file=f)
trstyle = ""
with db_open("ppips_%s.db" % tile_type.lower()) as fi:
for line in fi:
pip_name, pip_type = line.split()
trstyle = " bgcolor=\"#dddddd\"" if trstyle == "" else ""
print("<tr%s><td>%s</td><td>%s</td></tr>" % (trstyle, pip_name, pip_type), file=f)
print("<tr%s><td>%s</td><td>%s</td></tr>" %
(trstyle, pip_name, pip_type), file=f)
print("</table>", file=f)
print("</div>", file=f)

View File

@ -44,28 +44,24 @@ TEST(BitFieldGetTest, SelectMidway) {
TEST(BitFieldSetTest, WriteOneBit) {
uint32_t actual = prjxray::bit_field_set(
static_cast<uint32_t>(0x0), 23, 23,
static_cast<uint32_t>(0x1));
static_cast<uint32_t>(0x0), 23, 23, static_cast<uint32_t>(0x1));
EXPECT_EQ(actual, static_cast<uint32_t>(0x800000));
}
TEST(BitFieldSetTest, WriteOneBitWithOutOfRangeValue) {
uint32_t actual = prjxray::bit_field_set(
static_cast<uint32_t>(0x0), 23, 23,
static_cast<uint32_t>(0x3));
static_cast<uint32_t>(0x0), 23, 23, static_cast<uint32_t>(0x3));
EXPECT_EQ(actual, static_cast<uint32_t>(0x800000));
}
TEST(BitFieldSetTest, WriteMultipleBits) {
uint32_t actual = prjxray::bit_field_set(
static_cast<uint32_t>(0x0), 18, 8,
static_cast<uint32_t>(0x123));
static_cast<uint32_t>(0x0), 18, 8, static_cast<uint32_t>(0x123));
EXPECT_EQ(actual, static_cast<uint32_t>(0x12300));
}
TEST(BitFieldSetTest, WriteMultipleBitsWithOutOfRangeValue) {
uint32_t actual = prjxray::bit_field_set(
static_cast<uint32_t>(0x0), 18, 8,
static_cast<uint32_t>(0x1234));
static_cast<uint32_t>(0x0), 18, 8, static_cast<uint32_t>(0x1234));
EXPECT_EQ(actual, static_cast<uint32_t>(0x23400));
}

View File

@ -10,20 +10,20 @@ namespace prjxray {
static constexpr const char kSegbitsGlobPattern[] = "segbits_*.db";
std::vector<std::unique_ptr<prjxray::SegbitsFileReader>> Database::segbits() const {
std::vector<std::unique_ptr<prjxray::SegbitsFileReader>> Database::segbits()
const {
std::vector<std::unique_ptr<prjxray::SegbitsFileReader>> segbits;
glob_t segbits_glob_results;
int ret = glob(absl::StrCat(db_path_, "/", kSegbitsGlobPattern).c_str(),
GLOB_NOSORT | GLOB_TILDE,
NULL, &segbits_glob_results);
GLOB_NOSORT | GLOB_TILDE, NULL, &segbits_glob_results);
if (ret < 0) {
return {};
}
for(size_t idx = 0; idx < segbits_glob_results.gl_pathc; idx++) {
for (size_t idx = 0; idx < segbits_glob_results.gl_pathc; idx++) {
auto this_segbit = SegbitsFileReader::InitWithFile(
segbits_glob_results.gl_pathv[idx]);
segbits_glob_results.gl_pathv[idx]);
if (this_segbit) {
segbits.emplace_back(std::move(this_segbit));
}

View File

@ -8,9 +8,9 @@
namespace prjxray {
template<typename WordType, typename ByteType>
template <typename WordType, typename ByteType>
class BigEndianSpan {
public:
public:
constexpr static size_t kBytesPerElement = sizeof(WordType);
using byte_type = ByteType;
@ -18,43 +18,45 @@ class BigEndianSpan {
using size_type = std::size_t;
class value_type {
public:
public:
operator WordType() const {
WordType word = 0;
for(size_t ii = 0; ii < kBytesPerElement; ++ii) {
word |= (static_cast<WordType>(bytes_[ii]) << ((kBytesPerElement - 1 - ii) * 8));
for (size_t ii = 0; ii < kBytesPerElement; ++ii) {
word |= (static_cast<WordType>(bytes_[ii])
<< ((kBytesPerElement - 1 - ii) * 8));
}
return word;
}
value_type& operator=(WordType word) {
for (size_t ii = 0; ii < kBytesPerElement; ++ii) {
bytes_[ii] = ((word >> ((kBytesPerElement - 1 - ii) * 8)) & 0xFF);
bytes_[ii] =
((word >>
((kBytesPerElement - 1 - ii) * 8)) &
0xFF);
}
return *this;
}
protected:
protected:
friend class BigEndianSpan<WordType, ByteType>;
value_type(absl::Span<ByteType> bytes) : bytes_(bytes) {};
value_type(absl::Span<ByteType> bytes) : bytes_(bytes){};
private:
private:
absl::Span<ByteType> bytes_;
};
class iterator
: public std::iterator<std::input_iterator_tag, value_type> {
public:
value_type operator*() const {
return value_type(bytes_);
}
: public std::iterator<std::input_iterator_tag, value_type> {
public:
value_type operator*() const { return value_type(bytes_); }
bool operator==(const iterator &other) const {
bool operator==(const iterator& other) const {
return bytes_ == other.bytes_;
}
bool operator!=(const iterator &other) const {
bool operator!=(const iterator& other) const {
return bytes_ != other.bytes_;
}
@ -63,20 +65,19 @@ class BigEndianSpan {
return *this;
}
protected:
protected:
friend class BigEndianSpan<WordType, ByteType>;
iterator(absl::Span<ByteType> bytes) : bytes_(bytes) {};
iterator(absl::Span<ByteType> bytes) : bytes_(bytes){};
private:
private:
absl::Span<ByteType> bytes_;
};
using pointer = value_type*;
using reference = value_type&;
BigEndianSpan(absl::Span<ByteType> bytes) : bytes_(bytes) {};
BigEndianSpan(absl::Span<ByteType> bytes) : bytes_(bytes){};
constexpr size_type size() const noexcept {
return bytes_.size() / kBytesPerElement;
@ -88,7 +89,7 @@ class BigEndianSpan {
value_type operator[](size_type pos) const {
assert(pos >= 0 && pos < size());
return value_type(bytes_.subspan((pos*kBytesPerElement)));
return value_type(bytes_.subspan((pos * kBytesPerElement)));
}
constexpr reference at(size_type pos) const {
@ -98,16 +99,15 @@ class BigEndianSpan {
iterator begin() const { return iterator(bytes_); }
iterator end() const { return iterator({}); }
private:
private:
absl::Span<ByteType> bytes_;
};
template<typename WordType, typename Container>
template <typename WordType, typename Container>
BigEndianSpan<WordType, typename Container::value_type> make_big_endian_span(
Container &bytes) {
Container& bytes) {
return BigEndianSpan<WordType, typename Container::value_type>(
absl::Span<typename Container::value_type>(bytes));
absl::Span<typename Container::value_type>(bytes));
}
} // namespace prjxray

View File

@ -3,41 +3,44 @@
namespace prjxray {
template<typename UInt>
template <typename UInt>
constexpr UInt bit_mask(const int bit) {
return (static_cast<UInt>(1) << bit);
}
template<typename UInt>
template <typename UInt>
constexpr UInt bit_sizeof() {
return sizeof(UInt) * 8;
}
template<typename UInt>
template <typename UInt>
constexpr UInt bit_all_ones() {
return ~static_cast<UInt>(0);
}
template<typename UInt>
template <typename UInt>
constexpr UInt bit_mask_range(const int top_bit, const int bottom_bit) {
return ((bit_all_ones<UInt>() >> (bit_sizeof<UInt>() - 1 - top_bit)) &
(bit_all_ones<UInt>() - bit_mask<UInt>(bottom_bit) +
static_cast<UInt>(1)));
(bit_all_ones<UInt>() - bit_mask<UInt>(bottom_bit) +
static_cast<UInt>(1)));
}
template<typename UInt>
constexpr UInt bit_field_get(UInt value, const int top_bit, const int bottom_bit) {
return (value & bit_mask_range<UInt>(top_bit, bottom_bit)) >> bottom_bit;
template <typename UInt>
constexpr UInt bit_field_get(UInt value,
const int top_bit,
const int bottom_bit) {
return (value & bit_mask_range<UInt>(top_bit, bottom_bit)) >>
bottom_bit;
}
template<typename UInt, typename ValueType>
template <typename UInt, typename ValueType>
constexpr UInt bit_field_set(const UInt reg_value,
const int top_bit, const int bottom_bit,
const ValueType field_value) {
const int top_bit,
const int bottom_bit,
const ValueType field_value) {
return ((reg_value & ~bit_mask_range<UInt>(top_bit, bottom_bit)) |
((static_cast<UInt>(field_value) << bottom_bit) &
bit_mask_range<UInt>(top_bit, bottom_bit)));
((static_cast<UInt>(field_value) << bottom_bit) &
bit_mask_range<UInt>(top_bit, bottom_bit)));
}
} // namespace prjxray

View File

@ -10,16 +10,15 @@
namespace prjxray {
class Database {
public:
Database(const std::string &path)
: db_path_(path) {}
public:
Database(const std::string& path) : db_path_(path) {}
std::vector<std::unique_ptr<SegbitsFileReader>> segbits() const;
private:
private:
std::string db_path_;
};
} // namespace prjxray
#endif // PRJXRAY_LIB_DATABASE_H
#endif // PRJXRAY_LIB_DATABASE_H

View File

@ -9,11 +9,11 @@
namespace prjxray {
class MemoryMappedFile {
public:
public:
~MemoryMappedFile();
static std::unique_ptr<MemoryMappedFile> InitWithFile(
const std::string &path);
const std::string& path);
void* const data() const { return data_; }
const size_t size() const { return size_; }
@ -22,14 +22,13 @@ class MemoryMappedFile {
return {static_cast<uint8_t*>(data_), size_};
}
private:
MemoryMappedFile(void *data, size_t size)
: data_(data), size_(size) {};
private:
MemoryMappedFile(void* data, size_t size) : data_(data), size_(size){};
void *data_;
void* data_;
size_t size_;
};
} // namespace prjxray
} // namespace prjxray
#endif // PRJXRAY_LIB_MEMORY_MAPPED_FILE

View File

@ -10,39 +10,41 @@
namespace prjxray {
class SegbitsFileReader {
public:
public:
class value_type {
public:
public:
absl::string_view tag() const { return tag_; }
absl::string_view bit() const { return bit_; }
private:
private:
friend SegbitsFileReader;
value_type(const absl::string_view &view);
value_type(const absl::string_view& view);
absl::string_view tag_;
absl::string_view bit_;
};
class iterator
: public std::iterator<std::input_iterator_tag, value_type> {
public:
: public std::iterator<std::input_iterator_tag, value_type> {
public:
iterator& operator++();
bool operator==(iterator other) const {
return view_ == other.view_; }
return view_ == other.view_;
}
bool operator!=(iterator other) const {
return !(*this == other);}
return !(*this == other);
}
const value_type& operator*() const { return value_; }
const value_type* operator->() const { return &value_; }
protected:
protected:
explicit iterator(absl::string_view view)
: view_(view), value_(view) {}
: view_(view), value_(view) {}
private:
private:
friend SegbitsFileReader;
absl::string_view view_;
@ -50,18 +52,18 @@ class SegbitsFileReader {
};
static std::unique_ptr<SegbitsFileReader> InitWithFile(
const std::string &path);
const std::string& path);
iterator begin();
iterator end();
private:
SegbitsFileReader(std::unique_ptr<MemoryMappedFile> &&mapped_file)
: mapped_file_(std::move(mapped_file)) {};
private:
SegbitsFileReader(std::unique_ptr<MemoryMappedFile>&& mapped_file)
: mapped_file_(std::move(mapped_file)){};
std::unique_ptr<MemoryMappedFile> mapped_file_;
};
} // namespace prjxray
} // namespace prjxray
#endif // PRJXRAY_LIB_SEGBITS_FILE_READER_H

View File

@ -16,24 +16,24 @@ namespace xilinx {
namespace xc7series {
class BitstreamReader {
public:
public:
using value_type = ConfigurationPacket;
class iterator
: public std::iterator<std::input_iterator_tag, value_type> {
public:
: public std::iterator<std::input_iterator_tag, value_type> {
public:
iterator& operator++();
bool operator==(const iterator &other) const;
bool operator!=(const iterator &other) const;
bool operator==(const iterator& other) const;
bool operator!=(const iterator& other) const;
const value_type& operator*() const;
const value_type* operator->() const;
protected:
protected:
explicit iterator(absl::Span<uint32_t> words);
private:
private:
friend BitstreamReader;
ConfigurationPacket::ParseResult parse_result_;
@ -42,31 +42,32 @@ class BitstreamReader {
// Construct a reader from a collection of 32-bit, big-endian words.
// Assumes that any sync word has already been removed.
BitstreamReader(std::vector<uint32_t> &&words);
BitstreamReader(std::vector<uint32_t>&& words);
// Construct a `BitstreamReader` from a Container of bytes.
// Any bytes preceding an initial sync word are ignored.
template<typename T>
template <typename T>
static absl::optional<BitstreamReader> InitWithBytes(T bitstream);
const std::vector<uint32_t> &words() { return words_; };
const std::vector<uint32_t>& words() { return words_; };
// Returns an iterator that yields `ConfigurationPackets`
// as read from the bitstream.
iterator begin();
iterator end();
private:
private:
static std::array<uint8_t, 4> kSyncWord;
std::vector<uint32_t> words_;
};
template<typename T>
template <typename T>
absl::optional<BitstreamReader> BitstreamReader::InitWithBytes(T bitstream) {
// If this is really a Xilinx 7-Series bitstream, there will be a sync
// word somewhere toward the beginning.
auto sync_pos = std::search(bitstream.begin(), bitstream.end(),
kSyncWord.begin(), kSyncWord.end());
kSyncWord.begin(), kSyncWord.end());
if (sync_pos == bitstream.end()) {
return absl::optional<BitstreamReader>();
}
@ -74,13 +75,13 @@ absl::optional<BitstreamReader> BitstreamReader::InitWithBytes(T bitstream) {
// Wrap the provided container in a span that strips off the preamble.
absl::Span<typename T::value_type> bitstream_span(bitstream);
auto config_packets = bitstream_span.subspan(
sync_pos - bitstream.begin());
auto config_packets =
bitstream_span.subspan(sync_pos - bitstream.begin());
// Convert the bytes into 32-bit, big-endian words.
auto big_endian_reader = make_big_endian_span<uint32_t>(config_packets);
std::vector<uint32_t> words{big_endian_reader.begin(),
big_endian_reader.end()};
big_endian_reader.end()};
return BitstreamReader(std::move(words));
}

View File

@ -16,18 +16,18 @@ enum class BlockType : unsigned int {
/* reserved = 0x3, */
};
std::ostream &operator<<(std::ostream &o, BlockType value);
std::ostream& operator<<(std::ostream& o, BlockType value);
} // namespace xc7series
} // namespace xilinx
} // namespace prjxray
namespace YAML {
template<>
template <>
struct convert<prjxray::xilinx::xc7series::BlockType> {
static Node encode(const prjxray::xilinx::xc7series::BlockType &rhs);
static Node encode(const prjxray::xilinx::xc7series::BlockType& rhs);
static bool decode(const Node& node,
prjxray::xilinx::xc7series::BlockType &lhs);
prjxray::xilinx::xc7series::BlockType& lhs);
};
} // namespace YAML

View File

@ -14,30 +14,31 @@ namespace xilinx {
namespace xc7series {
class Configuration {
public:
using FrameMap = std::map<FrameAddress,
absl::Span<uint32_t>>;
public:
using FrameMap = std::map<FrameAddress, absl::Span<uint32_t>>;
template<typename Collection>
template <typename Collection>
static absl::optional<Configuration> InitWithPackets(
const Part& part, Collection &packets);
const Part& part,
Collection& packets);
Configuration(const Part& part, const FrameMap &frames)
: part_(part), frames_(std::move(frames)) {}
Configuration(const Part& part, const FrameMap& frames)
: part_(part), frames_(std::move(frames)) {}
const Part& part() const { return part_; }
const FrameMap& frames() const { return frames_; }
private:
private:
static constexpr int kWordsPerFrame = 101;
Part part_;
FrameMap frames_;
};
template<typename Collection>
template <typename Collection>
absl::optional<Configuration> Configuration::InitWithPackets(
const Part& part, Collection &packets) {
const Part& part,
Collection& packets) {
// Registers that can be directly written to.
uint32_t command_register = 0;
uint32_t frame_address_register = 0;
@ -55,95 +56,106 @@ absl::optional<Configuration> Configuration::InitWithPackets(
}
switch (packet.address()) {
case ConfigurationRegister::MASK:
if (packet.data().size() < 1) continue;
mask_register = packet.data()[0];
break;
case ConfigurationRegister::CTL1:
if (packet.data().size() < 1) continue;
ctl1_register = packet.data()[0] & mask_register;
break;
case ConfigurationRegister::CMD:
if (packet.data().size() < 1) continue;
command_register = packet.data()[0];
// Writes to CMD trigger an immediate action. In the case of
// WCFG, that is just setting a flag for the next FDIR.
if (command_register == 0x1) {
start_new_write = true;
}
break;
case ConfigurationRegister::IDCODE:
// This really should be a one-word write.
if (packet.data().size() < 1) continue;
// If the IDCODE doesn't match our expected part,
// consider the bitstream invalid.
if (packet.data()[0] != part.idcode()) {
return {};
}
break;
case ConfigurationRegister::FAR:
// This really should be a one-word write.
if (packet.data().size() < 1) continue;
frame_address_register = packet.data()[0];
// Per UG470, the command present in the CMD register
// is executed each time the FAR register is laoded
// with a new value. As we only care about WCFG
// commands, just check that here. CTRL1 is completely
// undocumented but looking at generated bitstreams, bit 21
// is used when per-frame CRC is enabled. Setting this
// bit seems to inhibit the re-execution of CMD during a
// FAR write. In practice, this is used so FAR writes
// can be added in the bitstream to show progress
// markers without impacting the actual write
// operation.
if (bit_field_get(ctl1_register, 21, 21) == 0 &&
command_register == 0x1) {
start_new_write = true;
}
break;
case ConfigurationRegister::FDRI: {
if (start_new_write) {
current_frame_address = frame_address_register;
start_new_write = false;
}
// 7-series frames are 101-words long. Writes to this
// register can be multiples of that to do
// auto-incrementing block writes.
for (size_t ii = 0;
ii < packet.data().size();
ii += kWordsPerFrame) {
frames[current_frame_address] =
packet.data().subspan(
ii, kWordsPerFrame);
auto next_address = part.GetNextFrameAddress(
current_frame_address);
if (!next_address) break;
// Bitstreams appear to have 2 frames of
// padding between rows.
if (next_address->row_address() !=
current_frame_address.row_address()) {
ii += 2 * kWordsPerFrame;
case ConfigurationRegister::MASK:
if (packet.data().size() < 1)
continue;
mask_register = packet.data()[0];
break;
case ConfigurationRegister::CTL1:
if (packet.data().size() < 1)
continue;
ctl1_register =
packet.data()[0] & mask_register;
break;
case ConfigurationRegister::CMD:
if (packet.data().size() < 1)
continue;
command_register = packet.data()[0];
// Writes to CMD trigger an immediate action. In
// the case of WCFG, that is just setting a flag
// for the next FDIR.
if (command_register == 0x1) {
start_new_write = true;
}
current_frame_address = *next_address;
break;
case ConfigurationRegister::IDCODE:
// This really should be a one-word write.
if (packet.data().size() < 1)
continue;
// If the IDCODE doesn't match our expected
// part, consider the bitstream invalid.
if (packet.data()[0] != part.idcode()) {
return {};
}
break;
case ConfigurationRegister::FAR:
// This really should be a one-word write.
if (packet.data().size() < 1)
continue;
frame_address_register = packet.data()[0];
// Per UG470, the command present in the CMD
// register is executed each time the FAR
// register is laoded with a new value. As we
// only care about WCFG commands, just check
// that here. CTRL1 is completely undocumented
// but looking at generated bitstreams, bit 21
// is used when per-frame CRC is enabled.
// Setting this bit seems to inhibit the
// re-execution of CMD during a FAR write. In
// practice, this is used so FAR writes can be
// added in the bitstream to show progress
// markers without impacting the actual write
// operation.
if (bit_field_get(ctl1_register, 21, 21) == 0 &&
command_register == 0x1) {
start_new_write = true;
}
break;
case ConfigurationRegister::FDRI: {
if (start_new_write) {
current_frame_address =
frame_address_register;
start_new_write = false;
}
// 7-series frames are 101-words long. Writes
// to this register can be multiples of that to
// do auto-incrementing block writes.
for (size_t ii = 0; ii < packet.data().size();
ii += kWordsPerFrame) {
frames[current_frame_address] =
packet.data().subspan(
ii, kWordsPerFrame);
auto next_address =
part.GetNextFrameAddress(
current_frame_address);
if (!next_address)
break;
// Bitstreams appear to have 2 frames of
// padding between rows.
if (next_address->row_address() !=
current_frame_address
.row_address()) {
ii += 2 * kWordsPerFrame;
}
current_frame_address = *next_address;
}
break;
}
break;
}
default:
break;
default:
break;
}
}
return Configuration(part, frames);
}
} // namespace xc7series
} // namespace xilinx
} // namespace prjxray
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_H_
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_H_

View File

@ -11,11 +11,11 @@ namespace xilinx {
namespace xc7series {
class ConfigurationFrameRange {
public:
public:
ConfigurationFrameRange() : begin_(0), end_(0) {}
ConfigurationFrameRange(FrameAddress begin, FrameAddress end)
: begin_(begin), end_(end) {};
: begin_(begin), end_(end){};
FrameAddress begin() const { return begin_; }
FrameAddress end() const { return end_; }
@ -25,7 +25,7 @@ class ConfigurationFrameRange {
bool Contains(FrameAddress address) const;
private:
private:
FrameAddress begin_;
FrameAddress end_;
};
@ -35,13 +35,13 @@ class ConfigurationFrameRange {
} // namespace prjxray
namespace YAML {
template<>
template <>
struct convert<prjxray::xilinx::xc7series::ConfigurationFrameRange> {
static Node encode(
const prjxray::xilinx::xc7series::ConfigurationFrameRange &rhs);
const prjxray::xilinx::xc7series::ConfigurationFrameRange& rhs);
static bool decode(
const Node& node,
prjxray::xilinx::xc7series::ConfigurationFrameRange &lhs);
const Node& node,
prjxray::xilinx::xc7series::ConfigurationFrameRange& lhs);
};
} // namespace YAML
} // namespace YAML
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_FRAME_RANGE_H_

View File

@ -12,10 +12,10 @@ namespace xilinx {
namespace xc7series {
class ConfigurationPacket {
public:
public:
typedef std::pair<absl::Span<uint32_t>,
absl::optional<ConfigurationPacket>>
ParseResult;
absl::optional<ConfigurationPacket>>
ParseResult;
enum Opcode {
NOP = 0,
@ -24,11 +24,14 @@ class ConfigurationPacket {
/* reserved = 3 */
};
ConfigurationPacket(unsigned int header_type, Opcode opcode,
ConfigurationRegister address,
const absl::Span<uint32_t> &data)
: header_type_(header_type), opcode_(opcode),
address_(address), data_(std::move(data)) {}
ConfigurationPacket(unsigned int header_type,
Opcode opcode,
ConfigurationRegister address,
const absl::Span<uint32_t>& data)
: header_type_(header_type),
opcode_(opcode),
address_(address),
data_(std::move(data)) {}
// Attempt to read a configuration packet from a sequence of
// 32-bit, big-endian words. If successful, returns the packet read and
@ -38,22 +41,22 @@ class ConfigurationPacket {
// packet is produced. If no valid header is found, an empty span is
// returned.
static ParseResult InitWithWords(
absl::Span<uint32_t> words,
const ConfigurationPacket *previous_packet = nullptr);
absl::Span<uint32_t> words,
const ConfigurationPacket* previous_packet = nullptr);
unsigned int header_type() const { return header_type_; }
const Opcode opcode() const { return opcode_; }
const ConfigurationRegister address() const { return address_; }
const absl::Span<uint32_t> &data() const { return data_; }
const absl::Span<uint32_t>& data() const { return data_; }
private:
private:
unsigned int header_type_;
Opcode opcode_;
ConfigurationRegister address_;
absl::Span<uint32_t> data_;
};
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket &packet);
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket& packet);
} // namespace xc7series
} // namespace xilinx

View File

@ -8,29 +8,29 @@ namespace xilinx {
namespace xc7series {
enum class ConfigurationRegister : unsigned int {
CRC = 0x00,
FAR = 0x01,
FDRI = 0x02,
FDRO = 0x03,
CMD = 0x04,
CTL0 = 0x05,
MASK = 0x06,
STAT = 0x07,
LOUT = 0x08,
COR0 = 0x09,
MFWR = 0x0a,
CBC = 0x0b,
IDCODE = 0x0c,
AXSS = 0x0d,
COR1 = 0x0e,
WBSTAR = 0x10,
TIMER = 0x11,
CRC = 0x00,
FAR = 0x01,
FDRI = 0x02,
FDRO = 0x03,
CMD = 0x04,
CTL0 = 0x05,
MASK = 0x06,
STAT = 0x07,
LOUT = 0x08,
COR0 = 0x09,
MFWR = 0x0a,
CBC = 0x0b,
IDCODE = 0x0c,
AXSS = 0x0d,
COR1 = 0x0e,
WBSTAR = 0x10,
TIMER = 0x11,
BOOTSTS = 0x16,
CTL1 = 0x18,
BSPI = 0x1F,
CTL1 = 0x18,
BSPI = 0x1F,
};
std::ostream& operator<<(std::ostream &o, const ConfigurationRegister &value);
std::ostream& operator<<(std::ostream& o, const ConfigurationRegister& value);
} // namespace xc7series
} // namespace xilinx

View File

@ -12,14 +12,16 @@ namespace xilinx {
namespace xc7series {
class FrameAddress {
public:
public:
FrameAddress() : address_(0) {}
FrameAddress(uint32_t address)
: address_(address) {};
FrameAddress(uint32_t address) : address_(address){};
FrameAddress(BlockType block_type, bool is_bottom_half_rows,
uint8_t row, uint16_t column, uint8_t minor);
FrameAddress(BlockType block_type,
bool is_bottom_half_rows,
uint8_t row,
uint16_t column,
uint8_t minor);
operator uint32_t() const { return address_; }
@ -29,22 +31,22 @@ class FrameAddress {
uint16_t column_address() const;
uint8_t minor_address() const;
private:
private:
uint32_t address_;
};
std::ostream &operator<<(std::ostream &o, const FrameAddress& addr);
std::ostream& operator<<(std::ostream& o, const FrameAddress& addr);
} // namespace xc7series
} // namespace xilinx
} // namespace prjxray
namespace YAML {
template<>
template <>
struct convert<prjxray::xilinx::xc7series::FrameAddress> {
static Node encode(const prjxray::xilinx::xc7series::FrameAddress &rhs);
static Node encode(const prjxray::xilinx::xc7series::FrameAddress& rhs);
static bool decode(const Node& node,
prjxray::xilinx::xc7series::FrameAddress &lhs);
prjxray::xilinx::xc7series::FrameAddress& lhs);
};
} // namespace YAML
} // namespace YAML
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_FRAME_ADDRESS_H_

View File

@ -4,38 +4,40 @@
#include <vector>
#include <absl/types/optional.h>
#include <prjxray/xilinx/xc7series/frame_address.h>
#include <prjxray/xilinx/xc7series/configuration_frame_range.h>
#include <prjxray/xilinx/xc7series/frame_address.h>
namespace prjxray {
namespace xilinx {
namespace xc7series {
class Part {
public:
static absl::optional<Part> FromFile(const std::string &path);
public:
static absl::optional<Part> FromFile(const std::string& path);
// Constructs an invalid part with a zero IDCODE. Required for YAML
// conversion but shouldn't be used otherwise.
Part() : idcode_(0), frame_ranges_() {}
Part(uint32_t idcode,
const std::vector<ConfigurationFrameRange> &ranges)
: idcode_(idcode), frame_ranges_(std::move(ranges)) {}
const std::vector<ConfigurationFrameRange>& ranges)
: idcode_(idcode), frame_ranges_(std::move(ranges)) {}
uint32_t idcode() const { return idcode_; }
const std::vector<ConfigurationFrameRange>&
configuration_frame_ranges() const { return frame_ranges_; }
const std::vector<ConfigurationFrameRange>& configuration_frame_ranges()
const {
return frame_ranges_;
}
absl::optional<FrameAddress>
GetNextFrameAddress(FrameAddress address) const;
absl::optional<FrameAddress> GetNextFrameAddress(
FrameAddress address) const;
private:
uint32_t idcode_;
private:
uint32_t idcode_;
// Ranges are expected to be non-overlapping.
std::vector<ConfigurationFrameRange> frame_ranges_;
// Ranges are expected to be non-overlapping.
std::vector<ConfigurationFrameRange> frame_ranges_;
};
} // namespace xc7series
@ -43,12 +45,12 @@ class Part {
} // namespace prjxray
namespace YAML {
template<>
template <>
struct convert<prjxray::xilinx::xc7series::Part> {
static Node encode(const prjxray::xilinx::xc7series::Part &rhs);
static Node encode(const prjxray::xilinx::xc7series::Part& rhs);
static bool decode(const Node& node,
prjxray::xilinx::xc7series::Part &lhs);
prjxray::xilinx::xc7series::Part& lhs);
};
} // namespace YAML
} // namespace YAML
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_PART_H_
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_PART_H_

View File

@ -2,17 +2,17 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
namespace prjxray {
std::unique_ptr<MemoryMappedFile> MemoryMappedFile::InitWithFile(
const std::string &path) {
const std::string& path) {
int fd = open(path.c_str(), O_RDONLY, 0);
if (fd == -1) return nullptr;
if (fd == -1)
return nullptr;
struct stat statbuf;
if (fstat(fd, &statbuf) < 0) {
@ -26,25 +26,26 @@ std::unique_ptr<MemoryMappedFile> MemoryMappedFile::InitWithFile(
if (statbuf.st_size == 0) {
close(fd);
return std::unique_ptr<MemoryMappedFile>(
new MemoryMappedFile(nullptr, 0));
new MemoryMappedFile(nullptr, 0));
}
void *file_map = mmap(NULL, statbuf.st_size, PROT_READ,
MAP_PRIVATE | MAP_POPULATE, fd, 0);
void* file_map = mmap(NULL, statbuf.st_size, PROT_READ,
MAP_PRIVATE | MAP_POPULATE, fd, 0);
// If mmap() succeeded, the fd is no longer needed as the mapping will
// keep the file open. If mmap() failed, the fd needs to be closed
// anyway.
close(fd);
if (file_map == MAP_FAILED) return nullptr;
if (file_map == MAP_FAILED)
return nullptr;
return std::unique_ptr<MemoryMappedFile>(
new MemoryMappedFile(file_map, statbuf.st_size));
new MemoryMappedFile(file_map, statbuf.st_size));
}
MemoryMappedFile::~MemoryMappedFile() {
munmap(data_, size_);
}
} // namepsace prjxray
} // namespace prjxray

View File

@ -3,26 +3,26 @@
namespace prjxray {
std::unique_ptr<SegbitsFileReader> SegbitsFileReader::InitWithFile(
const std::string &path) {
const std::string& path) {
auto mapped_file = MemoryMappedFile::InitWithFile(path);
if (!mapped_file) return nullptr;
if (!mapped_file)
return nullptr;
return std::unique_ptr<SegbitsFileReader>(
new SegbitsFileReader(std::move(mapped_file)));
new SegbitsFileReader(std::move(mapped_file)));
}
SegbitsFileReader::iterator SegbitsFileReader::begin() {
return iterator(absl::string_view(
static_cast<const char*>(mapped_file_->data()),
mapped_file_->size()));
return iterator(
absl::string_view(static_cast<const char*>(mapped_file_->data()),
mapped_file_->size()));
}
SegbitsFileReader::iterator SegbitsFileReader::end() {
return iterator(absl::string_view());
}
SegbitsFileReader::value_type::value_type(const absl::string_view &view) {
SegbitsFileReader::value_type::value_type(const absl::string_view& view) {
size_t separator_start = view.find_first_of(" \t");
if (separator_start == absl::string_view::npos) {
tag_ = view;
@ -55,5 +55,4 @@ SegbitsFileReader::iterator& SegbitsFileReader::iterator::operator++() {
return *this;
}
} // namespace prjxray

View File

@ -6,12 +6,13 @@
#include <gtest/gtest.h>
TEST(SegbitsFileReaderTest, NonExistantFileReturnsNull) {
EXPECT_FALSE(prjxray::SegbitsFileReader::InitWithFile("does_not_exist"));
EXPECT_FALSE(
prjxray::SegbitsFileReader::InitWithFile("does_not_exist"));
}
TEST(SegbitsFileReaderTest, ZeroLengthFileYieldsNoItems) {
auto segbits_reader =
prjxray::SegbitsFileReader::InitWithFile("empty_file");
prjxray::SegbitsFileReader::InitWithFile("empty_file");
ASSERT_TRUE(segbits_reader);
EXPECT_EQ(segbits_reader->begin(), segbits_reader->end());
@ -19,7 +20,7 @@ TEST(SegbitsFileReaderTest, ZeroLengthFileYieldsNoItems) {
TEST(SegbitsFileReaderTest, FileWithOneEntry) {
auto segbits_reader =
prjxray::SegbitsFileReader::InitWithFile("one_entry.segbits");
prjxray::SegbitsFileReader::InitWithFile("one_entry.segbits");
ASSERT_TRUE(segbits_reader);
auto begin_iter = segbits_reader->begin();
@ -31,7 +32,7 @@ TEST(SegbitsFileReaderTest, FileWithOneEntry) {
TEST(SegbitsFileReaderTest, FileWithOneEntryWithEmptyTag) {
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
"one_entry_empty_tag.segbits");
"one_entry_empty_tag.segbits");
ASSERT_TRUE(segbits_reader);
auto begin_iter = segbits_reader->begin();
@ -43,7 +44,7 @@ TEST(SegbitsFileReaderTest, FileWithOneEntryWithEmptyTag) {
TEST(SegbitsFileReaderTest, FileWithOneEntryMissingBit) {
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
"one_entry_missing_bit.segbits");
"one_entry_missing_bit.segbits");
ASSERT_TRUE(segbits_reader);
auto begin_iter = segbits_reader->begin();
@ -55,7 +56,7 @@ TEST(SegbitsFileReaderTest, FileWithOneEntryMissingBit) {
TEST(SegbitsFileReaderTest, FileWithOneEntryWithExtraWhitespace) {
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
"one_entry_extra_whitespace.segbits");
"one_entry_extra_whitespace.segbits");
ASSERT_TRUE(segbits_reader);
auto begin_iter = segbits_reader->begin();
@ -66,8 +67,8 @@ TEST(SegbitsFileReaderTest, FileWithOneEntryWithExtraWhitespace) {
}
TEST(SegbitsFileReaderTest, FileWithTwoEntries) {
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
"two_entries.segbits");
auto segbits_reader =
prjxray::SegbitsFileReader::InitWithFile("two_entries.segbits");
ASSERT_TRUE(segbits_reader);
auto iter = segbits_reader->begin();

View File

@ -6,8 +6,8 @@ namespace xc7series {
std::array<uint8_t, 4> BitstreamReader::kSyncWord{0xAA, 0x99, 0x55, 0x66};
BitstreamReader::BitstreamReader(std::vector<uint32_t> &&words)
: words_(std::move(words)) {}
BitstreamReader::BitstreamReader(std::vector<uint32_t>&& words)
: words_(std::move(words)) {}
BitstreamReader::iterator BitstreamReader::begin() {
return iterator(absl::MakeSpan(words_));
@ -23,14 +23,12 @@ BitstreamReader::iterator::iterator(absl::Span<uint32_t> words) {
++(*this);
}
BitstreamReader::iterator&
BitstreamReader::iterator::operator++() {
BitstreamReader::iterator& BitstreamReader::iterator::operator++() {
do {
auto new_result = ConfigurationPacket::InitWithWords(
parse_result_.first,
parse_result_.second.has_value() ?
parse_result_.second.operator->() :
nullptr);
parse_result_.first, parse_result_.second.has_value()
? parse_result_.second.operator->()
: nullptr);
// If the a valid header is being found but there are
// insufficient words to yield a packet, consider it the end.
@ -41,8 +39,7 @@ BitstreamReader::iterator::operator++() {
words_ = parse_result_.first;
parse_result_ = new_result;
} while (!parse_result_.first.empty() &&
!parse_result_.second);
} while (!parse_result_.first.empty() && !parse_result_.second);
if (!parse_result_.second) {
words_ = absl::Span<uint32_t>();
@ -51,21 +48,21 @@ BitstreamReader::iterator::operator++() {
return *this;
}
bool BitstreamReader::iterator::operator==(const iterator &other) const {
bool BitstreamReader::iterator::operator==(const iterator& other) const {
return words_ == other.words_;
}
bool BitstreamReader::iterator::operator!=(const iterator &other) const {
bool BitstreamReader::iterator::operator!=(const iterator& other) const {
return !(*this == other);
}
const BitstreamReader::value_type&
BitstreamReader::iterator::operator*() const {
const BitstreamReader::value_type& BitstreamReader::iterator::operator*()
const {
return *(parse_result_.second);
}
const BitstreamReader::value_type*
BitstreamReader::iterator::operator->() const {
const BitstreamReader::value_type* BitstreamReader::iterator::operator->()
const {
return parse_result_.second.operator->();
}

View File

@ -19,30 +19,23 @@ TEST(BitstreamReaderTest, InitWithOnlySyncReturnsObject) {
EXPECT_TRUE(reader);
}
TEST(BitstreamReaderTest,
InitWithSyncAfterNonWordSizedPaddingReturnsObject) {
std::vector<uint8_t> bitstream{
0xFF, 0xFE,
0xAA, 0x99, 0x55, 0x66
};
TEST(BitstreamReaderTest, InitWithSyncAfterNonWordSizedPaddingReturnsObject) {
std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xAA, 0x99, 0x55, 0x66};
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
EXPECT_TRUE(reader);
}
TEST(BitstreamReaderTest,
InitWithSyncAfterWordSizedPaddingReturnsObject) {
std::vector<uint8_t> bitstream{
0xFF, 0xFE, 0xFD, 0xFC,
0xAA, 0x99, 0x55, 0x66
};
TEST(BitstreamReaderTest, InitWithSyncAfterWordSizedPaddingReturnsObject) {
std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xFD, 0xFC,
0xAA, 0x99, 0x55, 0x66};
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
EXPECT_TRUE(reader);
}
TEST(BitstreamReaderTest, ParsesType1Packet) {
std::vector<uint8_t> bitstream{
0xAA, 0x99, 0x55, 0x66, // sync
0x20, 0x00, 0x00, 0x00, // NOP
0xAA, 0x99, 0x55, 0x66, // sync
0x20, 0x00, 0x00, 0x00, // NOP
};
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
ASSERT_TRUE(reader);
@ -50,34 +43,31 @@ TEST(BitstreamReaderTest, ParsesType1Packet) {
auto first_packet = reader->begin();
EXPECT_EQ(first_packet->opcode(),
xc7series::ConfigurationPacket::Opcode::NOP);
xc7series::ConfigurationPacket::Opcode::NOP);
EXPECT_EQ(++first_packet, reader->end());
}
TEST(BitstreamReaderTest, ParseType2PacketWithoutType1Fails) {
std::vector<uint8_t> bitstream{
0xAA, 0x99, 0x55, 0x66, // sync
0x40, 0x00, 0x00, 0x00, // Type 2 NOP
0xAA, 0x99, 0x55, 0x66, // sync
0x40, 0x00, 0x00, 0x00, // Type 2 NOP
};
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
ASSERT_TRUE(reader);
EXPECT_EQ(reader->begin(), reader->end());
}
TEST(BitstreamReaderTest, ParsesType2AfterType1Packet) {
std::vector<uint8_t> bitstream{
0xAA, 0x99, 0x55, 0x66, // sync
0x28, 0x00, 0x60, 0x00, // Type 1 Read zero bytes from 6
0x48, 0x00, 0x00, 0x04, // Type 2 write of 4 words
0x1, 0x2, 0x3, 0x4,
0x5, 0x6, 0x7, 0x8,
0x9, 0xA, 0xB, 0xC,
0xD, 0xE, 0xF, 0x10,
0xAA, 0x99, 0x55, 0x66, // sync
0x28, 0x00, 0x60, 0x00, // Type 1 Read zero bytes from 6
0x48, 0x00, 0x00, 0x04, // Type 2 write of 4 words
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10,
};
std::vector<uint32_t> data_words{
0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10};
std::vector<uint32_t> data_words{0x01020304, 0x05060708, 0x090A0B0C,
0x0D0E0F10};
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
ASSERT_TRUE(reader);
@ -85,17 +75,17 @@ TEST(BitstreamReaderTest, ParsesType2AfterType1Packet) {
auto first_packet = reader->begin();
EXPECT_EQ(first_packet->opcode(),
xc7series::ConfigurationPacket::Opcode::Read);
xc7series::ConfigurationPacket::Opcode::Read);
EXPECT_EQ(first_packet->address(),
xc7series::ConfigurationRegister::FDRO);
xc7series::ConfigurationRegister::FDRO);
EXPECT_EQ(first_packet->data(), absl::Span<uint32_t>());
auto second_packet = ++first_packet;
ASSERT_NE(second_packet, reader->end());
EXPECT_EQ(second_packet->opcode(),
xc7series::ConfigurationPacket::Opcode::Read);
xc7series::ConfigurationPacket::Opcode::Read);
EXPECT_EQ(second_packet->address(),
xc7series::ConfigurationRegister::FDRO);
xc7series::ConfigurationRegister::FDRO);
EXPECT_EQ(first_packet->data(), absl::Span<uint32_t>(data_words));
EXPECT_EQ(++first_packet, reader->end());

View File

@ -4,17 +4,17 @@ namespace prjxray {
namespace xilinx {
namespace xc7series {
std::ostream &operator<<(std::ostream &o, BlockType value) {
std::ostream& operator<<(std::ostream& o, BlockType value) {
switch (value) {
case BlockType::CLB_IO_CLK:
o << "CLB/IO/CLK";
break;
case BlockType::BLOCK_RAM:
o << "Block RAM";
break;
case BlockType::CFG_CLB:
o << "Config CLB";
break;
case BlockType::CLB_IO_CLK:
o << "CLB/IO/CLK";
break;
case BlockType::BLOCK_RAM:
o << "Block RAM";
break;
case BlockType::CFG_CLB:
o << "Config CLB";
break;
}
return o;
@ -27,7 +27,7 @@ std::ostream &operator<<(std::ostream &o, BlockType value) {
namespace YAML {
Node convert<prjxray::xilinx::xc7series::BlockType>::encode(
const prjxray::xilinx::xc7series::BlockType &rhs) {
const prjxray::xilinx::xc7series::BlockType& rhs) {
switch (rhs) {
case prjxray::xilinx::xc7series::BlockType::CLB_IO_CLK:
return Node("CLB_IO_CLK");
@ -41,7 +41,8 @@ Node convert<prjxray::xilinx::xc7series::BlockType>::encode(
}
bool YAML::convert<prjxray::xilinx::xc7series::BlockType>::decode(
const Node &node, prjxray::xilinx::xc7series::BlockType &lhs) {
const Node& node,
prjxray::xilinx::xc7series::BlockType& lhs) {
auto type_str = node.as<std::string>();
if (type_str == "CLB_IO_CLK") {
@ -58,4 +59,4 @@ bool YAML::convert<prjxray::xilinx::xc7series::BlockType>::decode(
}
}
} // namespace YAML;
} // namespace YAML

View File

@ -22,9 +22,9 @@ TEST(BlockTypeTest, YamlDecode) {
node.push_back("CLB_IO_CLK");
EXPECT_EQ(node[0].as<xc7series::BlockType>(),
xc7series::BlockType::CFG_CLB);
xc7series::BlockType::CFG_CLB);
EXPECT_EQ(node[1].as<xc7series::BlockType>(),
xc7series::BlockType::BLOCK_RAM);
xc7series::BlockType::BLOCK_RAM);
EXPECT_EQ(node[2].as<xc7series::BlockType>(),
xc7series::BlockType::CLB_IO_CLK);
xc7series::BlockType::CLB_IO_CLK);
}

View File

@ -17,7 +17,7 @@ namespace xc7series = prjxray::xilinx::xc7series;
namespace YAML {
Node convert<xc7series::ConfigurationFrameRange>::encode(
const xc7series::ConfigurationFrameRange &rhs) {
const xc7series::ConfigurationFrameRange& rhs) {
Node node;
node.SetTag("xilinx/xc7series/configuration_frame_range");
node["begin"] = rhs.begin();
@ -26,16 +26,16 @@ Node convert<xc7series::ConfigurationFrameRange>::encode(
}
bool convert<xc7series::ConfigurationFrameRange>::decode(
const Node &node,
xc7series::ConfigurationFrameRange &lhs) {
const Node& node,
xc7series::ConfigurationFrameRange& lhs) {
if (node.Tag() != "xilinx/xc7series/configuration_frame_range" ||
!node["begin"] ||
!node["end"]) return false;
!node["begin"] || !node["end"])
return false;
lhs = xc7series::ConfigurationFrameRange(
node["begin"].as<xc7series::FrameAddress>(),
node["end"].as<xc7series::FrameAddress>());
node["begin"].as<xc7series::FrameAddress>(),
node["end"].as<xc7series::FrameAddress>());
return true;
}
} // namespace YAML;
} // namespace YAML

View File

@ -11,65 +11,68 @@ namespace xc7series {
std::pair<absl::Span<uint32_t>, absl::optional<ConfigurationPacket>>
ConfigurationPacket::InitWithWords(absl::Span<uint32_t> words,
const ConfigurationPacket *previous_packet) {
const ConfigurationPacket* previous_packet) {
// Need at least one 32-bit word to have a valid packet header.
if (words.size() < 1) return {words, {}};
if (words.size() < 1)
return {words, {}};
uint32_t header_type = bit_field_get(words[0], 31, 29);
switch (header_type) {
case 0x0:
// Type 0 is emitted at the end of a configuration row when
// BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES. These seem
// to be padding that are interepreted as NOPs. Since Type 0
// packets don't exist according to UG470 and they seem to be
// zero-filled, just consume the bytes without generating a
// packet.
return {words.subspan(1), {}};
case 0x1: {
Opcode opcode = static_cast<Opcode>(
bit_field_get(words[0], 28, 27));
ConfigurationRegister address =
static_cast<ConfigurationRegister>(
bit_field_get(words[0], 26, 13));
uint32_t data_word_count = bit_field_get(words[0], 10, 0);
case 0x0:
// Type 0 is emitted at the end of a configuration row
// when BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES.
// These seem to be padding that are interepreted as
// NOPs. Since Type 0 packets don't exist according to
// UG470 and they seem to be zero-filled, just consume
// the bytes without generating a packet.
return {words.subspan(1), {}};
case 0x1: {
Opcode opcode = static_cast<Opcode>(
bit_field_get(words[0], 28, 27));
ConfigurationRegister address =
static_cast<ConfigurationRegister>(
bit_field_get(words[0], 26, 13));
uint32_t data_word_count =
bit_field_get(words[0], 10, 0);
// If the full packet has not been received, return as though
// no valid packet was found.
if (data_word_count > words.size() - 1) {
return {words, {}};
// If the full packet has not been received, return as
// though no valid packet was found.
if (data_word_count > words.size() - 1) {
return {words, {}};
}
return {words.subspan(data_word_count + 1),
{{header_type, opcode, address,
words.subspan(1, data_word_count)}}};
}
case 0x2: {
absl::optional<ConfigurationPacket> packet;
Opcode opcode = static_cast<Opcode>(
bit_field_get(words[0], 28, 27));
uint32_t data_word_count =
bit_field_get(words[0], 26, 0);
return {words.subspan(data_word_count+1),
{{header_type, opcode, address,
words.subspan(1, data_word_count)}}};
}
case 0x2: {
absl::optional<ConfigurationPacket> packet;
Opcode opcode = static_cast<Opcode>(
bit_field_get(words[0], 28, 27));
uint32_t data_word_count = bit_field_get(words[0], 26, 0);
// If the full packet has not been received, return as
// though no valid packet was found.
if (data_word_count > words.size() - 1) {
return {words, {}};
}
// If the full packet has not been received, return as though
// no valid packet was found.
if (data_word_count > words.size() - 1) {
return {words, {}};
if (previous_packet) {
packet = ConfigurationPacket(
header_type, opcode,
previous_packet->address(),
words.subspan(1, data_word_count));
}
return {words.subspan(data_word_count + 1), packet};
}
if (previous_packet) {
packet = ConfigurationPacket(
header_type, opcode,
previous_packet->address(),
words.subspan(1, data_word_count));
}
return {words.subspan(data_word_count + 1), packet};
}
default:
return {{}, {}};
default:
return {{}, {}};
}
}
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket &packet) {
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket& packet) {
switch (packet.opcode()) {
case ConfigurationPacket::Opcode::NOP:
o << "[NOP]" << std::endl;
@ -101,7 +104,7 @@ std::ostream& operator<<(std::ostream& o, const ConfigurationPacket &packet) {
o << std::setw(8) << std::hex;
o << packet.data()[ii] << " ";
if ((ii+1) % 4 == 0) {
if ((ii + 1) % 4 == 0) {
o << std::endl;
}
}

View File

@ -10,26 +10,26 @@ namespace xc7series = prjxray::xilinx::xc7series;
constexpr uint32_t kType1NOP = prjxray::bit_field_set<uint32_t>(0, 31, 29, 0x1);
constexpr uint32_t MakeType1(const int opcode, const int address,
const int word_count) {
constexpr uint32_t MakeType1(const int opcode,
const int address,
const int word_count) {
return prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x1),
28, 27, opcode),
26, 13, address),
10, 0, word_count);
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x1), 28, 27,
opcode),
26, 13, address),
10, 0, word_count);
}
constexpr uint32_t MakeType2(const int opcode, const int word_count) {
return prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x2),
28, 27, opcode),
26, 0, word_count);
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x2), 28, 27,
opcode),
26, 0, word_count);
}
TEST(ConfigPacket, InitWithZeroBytes) {
auto packet = xc7series::ConfigurationPacket::InitWithWords({});
@ -44,9 +44,9 @@ TEST(ConfigPacket, InitWithType1Nop) {
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
ASSERT_TRUE(packet.second);
EXPECT_EQ(packet.second->opcode(),
xc7series::ConfigurationPacket::Opcode::NOP);
xc7series::ConfigurationPacket::Opcode::NOP);
EXPECT_EQ(packet.second->address(),
xc7series::ConfigurationRegister::CRC);
xc7series::ConfigurationRegister::CRC);
EXPECT_EQ(packet.second->data(), absl::Span<uint32_t>());
}
@ -57,9 +57,9 @@ TEST(ConfigPacket, InitWithType1Read) {
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
ASSERT_TRUE(packet.second);
EXPECT_EQ(packet.second->opcode(),
xc7series::ConfigurationPacket::Opcode::Read);
xc7series::ConfigurationPacket::Opcode::Read);
EXPECT_EQ(packet.second->address(),
xc7series::ConfigurationRegister::FDRI);
xc7series::ConfigurationRegister::FDRI);
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
}
@ -70,9 +70,9 @@ TEST(ConfigPacket, InitWithType1Write) {
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
ASSERT_TRUE(packet.second);
EXPECT_EQ(packet.second->opcode(),
xc7series::ConfigurationPacket::Opcode::Write);
xc7series::ConfigurationPacket::Opcode::Write);
EXPECT_EQ(packet.second->address(),
xc7series::ConfigurationRegister::FDRO);
xc7series::ConfigurationRegister::FDRO);
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
}
@ -86,20 +86,19 @@ TEST(ConfigPacket, InitWithType2WithoutPreviousPacketFails) {
TEST(ConfigPacket, InitWithType2WithPreviousPacket) {
xc7series::ConfigurationPacket previous_packet(
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Read,
xc7series::ConfigurationRegister::MFWR,
absl::Span<uint32_t>());
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Read,
xc7series::ConfigurationRegister::MFWR, absl::Span<uint32_t>());
std::vector<uint32_t> words{
MakeType2(0x01, 12), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
MakeType2(0x01, 12), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
absl::Span<uint32_t> word_span(words);
auto packet = xc7series::ConfigurationPacket::InitWithWords(
word_span, &previous_packet);
word_span, &previous_packet);
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
ASSERT_TRUE(packet.second);
EXPECT_EQ(packet.second->opcode(),
xc7series::ConfigurationPacket::Opcode::Read);
xc7series::ConfigurationPacket::Opcode::Read);
EXPECT_EQ(packet.second->address(),
xc7series::ConfigurationRegister::MFWR);
xc7series::ConfigurationRegister::MFWR);
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
}

View File

@ -4,7 +4,7 @@ namespace prjxray {
namespace xilinx {
namespace xc7series {
std::ostream& operator<<(std::ostream &o, const ConfigurationRegister &value) {
std::ostream& operator<<(std::ostream& o, const ConfigurationRegister& value) {
switch (value) {
case ConfigurationRegister::CRC:
return o << "CRC";
@ -51,7 +51,6 @@ std::ostream& operator<<(std::ostream &o, const ConfigurationRegister &value) {
}
};
} // namespace xc7series
} // namespace xilinx
} // namespace prjxray

View File

@ -15,7 +15,7 @@ namespace xc7series = prjxray::xilinx::xc7series;
TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
std::vector<xc7series::ConfigurationFrameRange> test_part_ranges;
test_part_ranges.push_back(
xc7series::ConfigurationFrameRange(0x4567, 0x4568));
xc7series::ConfigurationFrameRange(0x4567, 0x4568));
xc7series::Part test_part(0x1234, test_part_ranges);
@ -25,33 +25,34 @@ TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
std::vector<uint32_t> frame(101, 0xAA);
std::vector<xc7series::ConfigurationPacket> packets{
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::IDCODE,
absl::MakeSpan(idcode),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FAR,
absl::MakeSpan(frame_address),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::CMD,
absl::MakeSpan(cmd),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FDRI,
absl::MakeSpan(frame),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::IDCODE,
absl::MakeSpan(idcode),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FAR,
absl::MakeSpan(frame_address),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::CMD,
absl::MakeSpan(cmd),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FDRI,
absl::MakeSpan(frame),
},
};
auto test_config = xc7series::Configuration::InitWithPackets(test_part, packets);
auto test_config =
xc7series::Configuration::InitWithPackets(test_part, packets);
ASSERT_TRUE(test_config);
EXPECT_EQ(test_config->part().idcode(), static_cast<uint32_t>(0x1234));
@ -62,9 +63,9 @@ TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
TEST(ConfigurationTest, ConstructFromPacketsWithAutoincrement) {
std::vector<xc7series::ConfigurationFrameRange> test_part_ranges;
test_part_ranges.push_back(
xc7series::ConfigurationFrameRange(0x4560, 0x4570));
xc7series::ConfigurationFrameRange(0x4560, 0x4570));
test_part_ranges.push_back(
xc7series::ConfigurationFrameRange(0x4580, 0x4590));
xc7series::ConfigurationFrameRange(0x4580, 0x4590));
xc7series::Part test_part(0x1234, test_part_ranges);
@ -75,88 +76,99 @@ TEST(ConfigurationTest, ConstructFromPacketsWithAutoincrement) {
std::fill_n(frame.begin() + 101, 101, 0xBB);
std::vector<xc7series::ConfigurationPacket> packets{
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::IDCODE,
absl::MakeSpan(idcode),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FAR,
absl::MakeSpan(frame_address),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::CMD,
absl::MakeSpan(cmd),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FDRI,
absl::MakeSpan(frame),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::IDCODE,
absl::MakeSpan(idcode),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FAR,
absl::MakeSpan(frame_address),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::CMD,
absl::MakeSpan(cmd),
},
{
static_cast<unsigned int>(0x1),
xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FDRI,
absl::MakeSpan(frame),
},
};
auto test_config = xc7series::Configuration::InitWithPackets(test_part, packets);
auto test_config =
xc7series::Configuration::InitWithPackets(test_part, packets);
ASSERT_TRUE(test_config);
absl::Span<uint32_t> frame_span(frame);
EXPECT_EQ(test_config->part().idcode(), static_cast<uint32_t>(0x1234));
EXPECT_EQ(test_config->frames().size(), static_cast<size_t>(2));
EXPECT_EQ(test_config->frames().at(0x456F), std::vector<uint32_t>(101, 0xAA));
EXPECT_EQ(test_config->frames().at(0x4580), std::vector<uint32_t>(101, 0xBB));
EXPECT_EQ(test_config->frames().at(0x456F),
std::vector<uint32_t>(101, 0xAA));
EXPECT_EQ(test_config->frames().at(0x4580),
std::vector<uint32_t>(101, 0xBB));
}
TEST(ConfigurationTest, DebugAndPerFrameCrcBitstreamsProduceEqualConfigurations) {
TEST(ConfigurationTest,
DebugAndPerFrameCrcBitstreamsProduceEqualConfigurations) {
auto part = xc7series::Part::FromFile("configuration_test.yaml");
ASSERT_TRUE(part);
auto debug_bitstream = prjxray::MemoryMappedFile::InitWithFile(
"configuration_test.debug.bit");
"configuration_test.debug.bit");
ASSERT_TRUE(debug_bitstream);
auto debug_reader = xc7series::BitstreamReader::InitWithBytes(
debug_bitstream->as_bytes());
debug_bitstream->as_bytes());
ASSERT_TRUE(debug_reader);
auto debug_configuration = xc7series::Configuration::InitWithPackets(
*part, *debug_reader);
auto debug_configuration =
xc7series::Configuration::InitWithPackets(*part, *debug_reader);
ASSERT_TRUE(debug_configuration);
auto perframecrc_bitstream = prjxray::MemoryMappedFile::InitWithFile(
"configuration_test.perframecrc.bit");
"configuration_test.perframecrc.bit");
ASSERT_TRUE(perframecrc_bitstream);
auto perframecrc_reader = xc7series::BitstreamReader::InitWithBytes(
perframecrc_bitstream->as_bytes());
perframecrc_bitstream->as_bytes());
ASSERT_TRUE(perframecrc_reader);
auto perframecrc_configuration = xc7series::Configuration::InitWithPackets(
*part, *perframecrc_reader);
auto perframecrc_configuration =
xc7series::Configuration::InitWithPackets(*part,
*perframecrc_reader);
ASSERT_TRUE(perframecrc_configuration);
for (auto debug_frame : debug_configuration->frames()) {
auto perframecrc_frame = perframecrc_configuration->frames().find(debug_frame.first);
if (perframecrc_frame == perframecrc_configuration->frames().end()) {
ADD_FAILURE() << debug_frame.first << ": missing in perframecrc bitstream";
auto perframecrc_frame =
perframecrc_configuration->frames().find(debug_frame.first);
if (perframecrc_frame ==
perframecrc_configuration->frames().end()) {
ADD_FAILURE() << debug_frame.first
<< ": missing in perframecrc bitstream";
continue;
}
for (int ii = 0; ii < 101; ++ii) {
EXPECT_EQ(perframecrc_frame->second[ii], debug_frame.second[ii])
<< debug_frame.first << ": word " << ii;
EXPECT_EQ(perframecrc_frame->second[ii],
debug_frame.second[ii])
<< debug_frame.first << ": word " << ii;
}
}
for (auto perframecrc_frame : perframecrc_configuration->frames()) {
auto debug_frame = debug_configuration->frames().find(perframecrc_frame.first);
auto debug_frame =
debug_configuration->frames().find(perframecrc_frame.first);
if (debug_frame == debug_configuration->frames().end()) {
ADD_FAILURE() << perframecrc_frame.first
<< ": unexpectedly present in perframecrc bitstream";
<< ": unexpectedly present in "
"perframecrc bitstream";
}
}
}
@ -166,47 +178,52 @@ TEST(ConfigurationTest, DebugAndNormalBitstreamsProduceEqualConfigurations) {
ASSERT_TRUE(part);
auto debug_bitstream = prjxray::MemoryMappedFile::InitWithFile(
"configuration_test.debug.bit");
"configuration_test.debug.bit");
ASSERT_TRUE(debug_bitstream);
auto debug_reader = xc7series::BitstreamReader::InitWithBytes(
debug_bitstream->as_bytes());
debug_bitstream->as_bytes());
ASSERT_TRUE(debug_reader);
auto debug_configuration = xc7series::Configuration::InitWithPackets(
*part, *debug_reader);
auto debug_configuration =
xc7series::Configuration::InitWithPackets(*part, *debug_reader);
ASSERT_TRUE(debug_configuration);
auto normal_bitstream = prjxray::MemoryMappedFile::InitWithFile(
"configuration_test.bit");
auto normal_bitstream =
prjxray::MemoryMappedFile::InitWithFile("configuration_test.bit");
ASSERT_TRUE(normal_bitstream);
auto normal_reader = xc7series::BitstreamReader::InitWithBytes(
normal_bitstream->as_bytes());
normal_bitstream->as_bytes());
ASSERT_TRUE(normal_reader);
auto normal_configuration = xc7series::Configuration::InitWithPackets(
*part, *normal_reader);
auto normal_configuration =
xc7series::Configuration::InitWithPackets(*part, *normal_reader);
ASSERT_TRUE(normal_configuration);
for (auto debug_frame : debug_configuration->frames()) {
auto normal_frame = normal_configuration->frames().find(debug_frame.first);
auto normal_frame =
normal_configuration->frames().find(debug_frame.first);
if (normal_frame == normal_configuration->frames().end()) {
ADD_FAILURE() << debug_frame.first << ": missing in normal bitstream";
ADD_FAILURE() << debug_frame.first
<< ": missing in normal bitstream";
continue;
}
for (int ii = 0; ii < 101; ++ii) {
EXPECT_EQ(normal_frame->second[ii], debug_frame.second[ii])
<< debug_frame.first << ": word " << ii;
EXPECT_EQ(normal_frame->second[ii],
debug_frame.second[ii])
<< debug_frame.first << ": word " << ii;
}
}
for (auto normal_frame : normal_configuration->frames()) {
auto debug_frame = debug_configuration->frames().find(normal_frame.first);
auto debug_frame =
debug_configuration->frames().find(normal_frame.first);
if (debug_frame == debug_configuration->frames().end()) {
ADD_FAILURE() << normal_frame.first
<< ": unexpectedly present in normal bitstream";
ADD_FAILURE()
<< normal_frame.first
<< ": unexpectedly present in normal bitstream";
}
}
}

View File

@ -8,8 +8,11 @@ namespace prjxray {
namespace xilinx {
namespace xc7series {
FrameAddress::FrameAddress(BlockType block_type, bool is_bottom_half_rows,
uint8_t row, uint16_t column, uint8_t minor) {
FrameAddress::FrameAddress(BlockType block_type,
bool is_bottom_half_rows,
uint8_t row,
uint16_t column,
uint8_t minor) {
address_ = bit_field_set(0, 25, 23, block_type);
address_ = bit_field_set(address_, 22, 22, is_bottom_half_rows);
address_ = bit_field_set(address_, 21, 17, row);
@ -37,23 +40,16 @@ uint8_t FrameAddress::minor_address() const {
return bit_field_get(address_, 6, 0);
}
std::ostream &operator<<(std::ostream &o, const FrameAddress& addr) {
o << "["
<< std::hex << std::showbase << std::setw(10)
<< static_cast<uint32_t>(addr)
<< "] "
<< (addr.is_bottom_half_rows() ? "BOTTOM" : "TOP")
<< " Row="
<< std::setw(2) << std::dec
std::ostream& operator<<(std::ostream& o, const FrameAddress& addr) {
o << "[" << std::hex << std::showbase << std::setw(10)
<< static_cast<uint32_t>(addr) << "] "
<< (addr.is_bottom_half_rows() ? "BOTTOM" : "TOP")
<< " Row=" << std::setw(2) << std::dec
<< static_cast<unsigned int>(addr.row_address())
<< " Column="
<< std::setw(2) << std::dec
<< addr.column_address()
<< " Minor="
<< std::setw(2) << std::dec
<< " Column=" << std::setw(2) << std::dec << addr.column_address()
<< " Minor=" << std::setw(2) << std::dec
<< static_cast<unsigned int>(addr.minor_address())
<< " Type="
<< addr.block_type();
<< " Type=" << addr.block_type();
return o;
}
@ -66,7 +62,7 @@ namespace YAML {
namespace xc7series = prjxray::xilinx::xc7series;
Node convert<xc7series::FrameAddress>::encode(
const xc7series::FrameAddress &rhs) {
const xc7series::FrameAddress& rhs) {
Node node;
node.SetTag("xilinx/xc7series/frame_address");
node["block_type"] = rhs.block_type();
@ -77,15 +73,13 @@ Node convert<xc7series::FrameAddress>::encode(
return node;
}
bool convert<xc7series::FrameAddress>::decode(
const Node &node, xc7series::FrameAddress &lhs) {
bool convert<xc7series::FrameAddress>::decode(const Node& node,
xc7series::FrameAddress& lhs) {
if (!(node.Tag() == "xilinx/xc7series/frame_address" ||
node.Tag() == "xilinx/xc7series/configuration_frame_address") ||
!node["block_type"] ||
!node["row_half"] ||
!node["row"] ||
!node["column"] ||
!node["minor"]) return false;
!node["block_type"] || !node["row_half"] || !node["row"] ||
!node["column"] || !node["minor"])
return false;
bool row_half;
if (node["row_half"].as<std::string>() == "top") {
@ -97,12 +91,10 @@ bool convert<xc7series::FrameAddress>::decode(
}
lhs = prjxray::xilinx::xc7series::FrameAddress(
node["block_type"].as<xc7series::BlockType>(),
row_half,
node["row"].as<unsigned int>(),
node["column"].as<unsigned int>(),
node["minor"].as<unsigned int>());
node["block_type"].as<xc7series::BlockType>(), row_half,
node["row"].as<unsigned int>(), node["column"].as<unsigned int>(),
node["minor"].as<unsigned int>());
return true;
}
} // namespace YAML;
} // namespace YAML

View File

@ -5,8 +5,8 @@
namespace xc7series = prjxray::xilinx::xc7series;
TEST(FrameAddressTest, YamlEncode) {
xc7series::FrameAddress address(xc7series::BlockType::BLOCK_RAM,
false, 10, 0, 5);
xc7series::FrameAddress address(xc7series::BlockType::BLOCK_RAM, false,
10, 0, 5);
YAML::Node node(address);
@ -27,8 +27,7 @@ TEST(FrameAddressTest, YamlDecode) {
node["column"] = "5";
node["minor"] = "11";
xc7series::FrameAddress address =
node.as<xc7series::FrameAddress>();
xc7series::FrameAddress address = node.as<xc7series::FrameAddress>();
EXPECT_EQ(address.block_type(), xc7series::BlockType::BLOCK_RAM);
EXPECT_TRUE(address.is_bottom_half_rows());
EXPECT_EQ(address.row_address(), 0);

View File

@ -7,7 +7,7 @@ namespace prjxray {
namespace xilinx {
namespace xc7series {
absl::optional<Part> Part::FromFile(const std::string &path) {
absl::optional<Part> Part::FromFile(const std::string& path) {
try {
YAML::Node yaml = YAML::LoadFile(path);
return yaml.as<Part>();
@ -16,8 +16,8 @@ absl::optional<Part> Part::FromFile(const std::string &path) {
}
}
absl::optional<FrameAddress>
Part::GetNextFrameAddress(FrameAddress address) const {
absl::optional<FrameAddress> Part::GetNextFrameAddress(
FrameAddress address) const {
// Start with the next linear address.
FrameAddress target_address(address + 1);
@ -27,8 +27,7 @@ Part::GetNextFrameAddress(FrameAddress address) const {
// address.
absl::optional<FrameAddress> closest_address;
int32_t closest_distance;
for (auto iter = frame_ranges_.begin();
iter != frame_ranges_.end();
for (auto iter = frame_ranges_.begin(); iter != frame_ranges_.end();
++iter) {
if (iter->Contains(target_address)) {
return target_address;
@ -36,8 +35,7 @@ Part::GetNextFrameAddress(FrameAddress address) const {
int32_t distance = iter->begin() - target_address;
if (distance > 0 &&
(!closest_address ||
distance < closest_distance)) {
(!closest_address || distance < closest_distance)) {
closest_address = iter->begin();
closest_distance = distance;
}
@ -54,7 +52,7 @@ namespace xc7series = prjxray::xilinx::xc7series;
namespace YAML {
Node convert<xc7series::Part>::encode(const xc7series::Part &rhs) {
Node convert<xc7series::Part>::encode(const xc7series::Part& rhs) {
Node node;
node.SetTag("xilinx/xc7series/part");
@ -66,17 +64,16 @@ Node convert<xc7series::Part>::encode(const xc7series::Part &rhs) {
return node;
}
bool convert<xc7series::Part>::decode(const Node &node, xc7series::Part &lhs) {
if (node.Tag() != "xilinx/xc7series/part" ||
!node["idcode"] ||
!node["configuration_ranges"]) return false;
bool convert<xc7series::Part>::decode(const Node& node, xc7series::Part& lhs) {
if (node.Tag() != "xilinx/xc7series/part" || !node["idcode"] ||
!node["configuration_ranges"])
return false;
lhs = xc7series::Part(
node["idcode"].as<uint32_t>(),
node["configuration_ranges"].as<
std::vector<xc7series::ConfigurationFrameRange>>());
node["idcode"].as<uint32_t>(),
node["configuration_ranges"]
.as<std::vector<xc7series::ConfigurationFrameRange>>());
return true;
}
} // namespace YAML;
} // namespace YAML

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
autopep8

View File

@ -1,10 +1,10 @@
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <set>
#include <string>
#include <vector>
#include <absl/strings/numbers.h>
@ -19,20 +19,27 @@
DEFINE_bool(c, false, "output '*' for repeating patterns");
DEFINE_bool(C, false, "do not ignore the checksum in each frame");
DEFINE_int32(f, -1, "only dump the specified frame (might be used more than once)");
DEFINE_string(F, "", "<first_frame_address>:<last_frame_address> only dump frame in the specified range");
DEFINE_int32(f,
-1,
"only dump the specified frame (might be used more than once)");
DEFINE_string(F,
"",
"<first_frame_address>:<last_frame_address> only dump frame in "
"the specified range");
DEFINE_string(o, "", "write machine-readable output file with config frames");
DEFINE_bool(p, false, "output a binary netpgm image");
DEFINE_bool(x, false, "use format 'bit_%%08x_%%03d_%%02d_t%%d_h%%d_r%%d_c%%d_m%%d'\n"
"The fields have the following meaning:\n"
" - complete 32 bit hex frame id\n"
" - word index with that frame (decimal)\n"
" - bit index with that word (decimal)\n"
" - decoded frame type from frame id\n"
" - decoded top/botttom from frame id (top=0)\n"
" - decoded row address from frame id\n"
" - decoded column address from frame id\n"
" - decoded minor address from frame id\n");
DEFINE_bool(x,
false,
"use format 'bit_%%08x_%%03d_%%02d_t%%d_h%%d_r%%d_c%%d_m%%d'\n"
"The fields have the following meaning:\n"
" - complete 32 bit hex frame id\n"
" - word index with that frame (decimal)\n"
" - bit index with that word (decimal)\n"
" - decoded frame type from frame id\n"
" - decoded top/botttom from frame id (top=0)\n"
" - decoded row address from frame id\n"
" - decoded column address from frame id\n"
" - decoded minor address from frame id\n");
DEFINE_bool(y, false, "use format 'bit_%%08x_%%03d_%%02d'");
DEFINE_bool(z, false, "skip zero frames (frames with all bits cleared) in o");
DEFINE_string(part_file, "", "YAML file describing a Xilinx 7-Series part");
@ -44,9 +51,9 @@ uint32_t frame_range_begin = 0, frame_range_end = 0;
std::vector<uint32_t> zero_frame(101);
int main(int argc, char **argv) {
int main(int argc, char** argv) {
gflags::SetUsageMessage(
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
gflags::ParseCommandLineFlags(&argc, &argv, true);
auto part = xc7series::Part::FromFile(FLAGS_part_file);
@ -60,7 +67,8 @@ int main(int argc, char **argv) {
}
if (!FLAGS_F.empty()) {
std::pair<std::string, std::string> p = absl::StrSplit(FLAGS_F, ":");
std::pair<std::string, std::string> p =
absl::StrSplit(FLAGS_F, ":");
frame_range_begin = strtol(p.first.c_str(), nullptr, 0);
frame_range_end = strtol(p.second.c_str(), nullptr, 0) + 1;
}
@ -68,59 +76,61 @@ int main(int argc, char **argv) {
absl::optional<xc7series::BitstreamReader> reader;
if (argc == 2) {
auto in_file_name = argv[1];
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
auto in_file =
prjxray::MemoryMappedFile::InitWithFile(in_file_name);
if (!in_file) {
std::cerr << "Can't open input file '" << in_file_name
<< "' for reading!" << std::endl;
<< "' for reading!" << std::endl;
return 1;
}
std::cout << "Bitstream size: " << in_file->size() << " bytes"
<< std::endl;
<< std::endl;
reader = xc7series::BitstreamReader::InitWithBytes(
in_file->as_bytes());
in_file->as_bytes());
} else {
std::vector<uint8_t> bitdata;
while (1) {
int c = getchar();
if (c == EOF) break;
if (c == EOF)
break;
bitdata.push_back(c);
}
std::cout << "Bitstream size: " << bitdata.size() << " bytes"
<< std::endl;
<< std::endl;
reader = xc7series::BitstreamReader::InitWithBytes(bitdata);
}
if (!reader) {
std::cerr << "Bitstream does not appear to be a Xilinx "
<< "7-series bitstream!" << std::endl;
<< "7-series bitstream!" << std::endl;
return 1;
}
std::cout << "Config size: " << reader->words().size()
<< " words" << std::endl;
std::cout << "Config size: " << reader->words().size() << " words"
<< std::endl;
auto config = xc7series::Configuration::InitWithPackets(*part, *reader);
if (!config) {
std::cerr << "Bitstream does not appear to be for this part"
<< std::endl;
<< std::endl;
return 1;
}
std::cout << "Number of configuration frames: "
<< config->frames().size() << std::endl;
<< config->frames().size() << std::endl;
FILE *f = stdout;
FILE* f = stdout;
if (!FLAGS_o.empty())
{
if (!FLAGS_o.empty()) {
f = fopen(FLAGS_o.c_str(), "w");
if (f == nullptr) {
printf("Can't open output file '%s' for writing!\n", FLAGS_o.c_str());
printf("Can't open output file '%s' for writing!\n",
FLAGS_o.c_str());
return 1;
}
} else {
@ -130,8 +140,7 @@ int main(int argc, char **argv) {
std::vector<std::vector<bool>> pgmdata;
std::vector<int> pgmsep;
for (auto &it : config->frames())
{
for (auto& it : config->frames()) {
if (FLAGS_z && it.second == zero_frame)
continue;
@ -139,67 +148,95 @@ int main(int argc, char **argv) {
continue;
if (frame_range_begin != frame_range_end &&
(it.first < frame_range_begin || frame_range_end <= it.first))
(it.first < frame_range_begin ||
frame_range_end <= it.first))
continue;
if (FLAGS_o.empty())
printf("Frame 0x%08x (Type=%d Top=%d Row=%d Column=%d Minor=%d):\n",
static_cast<uint32_t>(it.first), static_cast<unsigned int>(it.first.block_type()),
it.first.is_bottom_half_rows() ? 1 : 0,
it.first.row_address(), it.first.column_address(), it.first.minor_address());
printf(
"Frame 0x%08x (Type=%d Top=%d Row=%d Column=%d "
"Minor=%d):\n",
static_cast<uint32_t>(it.first),
static_cast<unsigned int>(it.first.block_type()),
it.first.is_bottom_half_rows() ? 1 : 0,
it.first.row_address(), it.first.column_address(),
it.first.minor_address());
if (FLAGS_p)
{
if (FLAGS_p) {
if (it.first.minor_address() == 0 && !pgmdata.empty())
pgmsep.push_back(pgmdata.size());
pgmdata.push_back(std::vector<bool>());
for (int i = 0; i < 101; i++)
for (int k = 0; k < 32; k++)
pgmdata.back().push_back((it.second.at(i) & (1 << k)) != 0);
}
else
if (FLAGS_x || FLAGS_y)
{
for (int k = 0; k < 32; k++)
pgmdata.back().push_back(
(it.second.at(i) & (1 << k)) != 0);
} else if (FLAGS_x || FLAGS_y) {
for (int i = 0; i < 101; i++)
for (int k = 0; k < 32; k++)
if ((i != 50 || k > 12 || FLAGS_C) && ((it.second.at(i) & (1 << k)) != 0)) {
if (FLAGS_x)
fprintf(f, "bit_%08x_%03d_%02d_t%d_h%d_r%d_c%d_m%d\n",
static_cast<uint32_t>(it.first),
i, k,
static_cast<unsigned int>(it.first.block_type()),
it.first.is_bottom_half_rows() ? 1 : 0,
it.first.row_address(), it.first.column_address(), it.first.minor_address());
else
fprintf(f, "bit_%08x_%03d_%02d\n", static_cast<uint32_t>(it.first), i, k);
}
for (int k = 0; k < 32; k++)
if ((i != 50 || k > 12 || FLAGS_C) &&
((it.second.at(i) & (1 << k)) !=
0)) {
if (FLAGS_x)
fprintf(
f,
"bit_%08x_%03d_%"
"02d_t%d_h%d_r%d_c%"
"d_m%d\n",
static_cast<
uint32_t>(
it.first),
i, k,
static_cast<
unsigned int>(
it.first
.block_type()),
it.first.is_bottom_half_rows()
? 1
: 0,
it.first
.row_address(),
it.first
.column_address(),
it.first
.minor_address());
else
fprintf(f,
"bit_%08x_%03d_"
"%02d\n",
static_cast<
uint32_t>(
it.first),
i, k);
}
if (FLAGS_o.empty())
fprintf(f, "\n");
}
else
{
} else {
if (!FLAGS_o.empty())
fprintf(f, ".frame 0x%08x\n", static_cast<uint32_t>(it.first));
fprintf(f, ".frame 0x%08x\n",
static_cast<uint32_t>(it.first));
for (int i = 0; i < 101; i++)
fprintf(f, "%08x%s", it.second.at(i) & ((i != 50 || FLAGS_C) ? 0xffffffff : 0xffffe000), (i % 6) == 5 ? "\n" : " ");
fprintf(f, "%08x%s",
it.second.at(i) &
((i != 50 || FLAGS_C) ? 0xffffffff
: 0xffffe000),
(i % 6) == 5 ? "\n" : " ");
fprintf(f, "\n\n");
}
}
if (FLAGS_p)
{
if (FLAGS_p) {
int width = pgmdata.size() + pgmsep.size();
int height = 101*32+100;
int height = 101 * 32 + 100;
fprintf(f, "P5 %d %d 15\n", width, height);
for (int y = 0, bit = 101*32-1; y < height; y++, bit--)
{
for (int x = 0, frame = 0, sep = 0; x < width; x++, frame++)
{
if (sep < int(pgmsep.size()) && frame == pgmsep.at(sep)) {
for (int y = 0, bit = 101 * 32 - 1; y < height; y++, bit--) {
for (int x = 0, frame = 0, sep = 0; x < width;
x++, frame++) {
if (sep < int(pgmsep.size()) &&
frame == pgmsep.at(sep)) {
fputc(8, f);
x++, sep++;
}
@ -221,4 +258,3 @@ int main(int argc, char **argv) {
printf("DONE\n");
return 0;
}

View File

@ -11,15 +11,14 @@ namespace xc7series = prjxray::xilinx::xc7series;
struct Action {
std::string name;
std::function<int(int, char*[])> handler;
std::function<int(int, char* [])> handler;
};
int ListConfigPackets(int argc, char *argv[]) {
int ListConfigPackets(int argc, char* argv[]) {
if (argc < 1) {
std::cerr << "ERROR: no input specified" << std::endl;
std::cerr << "Usage: " << argv[0]
<< "list_config_packets <bit_file>"
<< std::endl;
<< "list_config_packets <bit_file>" << std::endl;
return 1;
}
@ -27,15 +26,14 @@ int ListConfigPackets(int argc, char *argv[]) {
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
if (!in_file) {
std::cerr << "Unable to open bit file: " << in_file_name
<< std::endl;
<< std::endl;
return 1;
}
auto reader = xc7series::BitstreamReader::InitWithBytes(
in_file->as_bytes());
auto reader =
xc7series::BitstreamReader::InitWithBytes(in_file->as_bytes());
if (!reader) {
std::cerr << "Input doesn't look like a bitstream"
<< std::endl;
std::cerr << "Input doesn't look like a bitstream" << std::endl;
return 1;
}
@ -46,12 +44,12 @@ int ListConfigPackets(int argc, char *argv[]) {
return 0;
}
int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
int DumpDebugbitstreamFrameAddresses(int argc, char* argv[]) {
if (argc < 1) {
std::cerr << "ERROR: no input specified" << std::endl;
std::cerr << "Usage: " << argv[0]
<< "dump_debugbitstream_frame_addresses <bit_file>"
<< std::endl;
<< "dump_debugbitstream_frame_addresses <bit_file>"
<< std::endl;
return 1;
}
@ -59,17 +57,15 @@ int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
if (!in_file) {
std::cerr << "Unable to open bit file: " << in_file_name
<< std::endl;
<< std::endl;
return 1;
}
auto in_bytes = absl::Span<uint8_t>(
static_cast<uint8_t*>(in_file->data()),
in_file->size());
static_cast<uint8_t*>(in_file->data()), in_file->size());
auto reader = xc7series::BitstreamReader::InitWithBytes(in_bytes);
if (!reader) {
std::cerr << "Input doesn't look like a bitstream"
<< std::endl;
std::cerr << "Input doesn't look like a bitstream" << std::endl;
return 1;
}
@ -84,7 +80,7 @@ int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
if (packet.data().size() != 1) {
std::cerr << "Write to FAR with word_count != 1"
<< std::endl;
<< std::endl;
continue;
}
@ -94,20 +90,19 @@ int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
if (!found_one_lout) {
std::cerr << "No LOUT writes found. Was "
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
<< std::endl;
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
<< std::endl;
return 1;
}
return 0;
}
int GetDeviceId(int argc, char *argv[]) {
int GetDeviceId(int argc, char* argv[]) {
if (argc < 1) {
std::cerr << "ERROR: no input specified" << std::endl;
std::cerr << "Usage: " << argv[0]
<< "get_device_id <bit_file>"
<< std::endl;
std::cerr << "Usage: " << argv[0] << "get_device_id <bit_file>"
<< std::endl;
return 1;
}
@ -115,68 +110,65 @@ int GetDeviceId(int argc, char *argv[]) {
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
if (!in_file) {
std::cerr << "Unable to open bit file: " << in_file_name
<< std::endl;
<< std::endl;
return 1;
}
auto in_bytes = absl::Span<uint8_t>(
static_cast<uint8_t*>(in_file->data()),
in_file->size());
static_cast<uint8_t*>(in_file->data()), in_file->size());
auto reader = xc7series::BitstreamReader::InitWithBytes(in_bytes);
if (!reader) {
std::cerr << "Input doesn't look like a bitstream"
<< std::endl;
std::cerr << "Input doesn't look like a bitstream" << std::endl;
return 1;
}
auto idcode_packet = std::find_if(
reader->begin(), reader->end(),
[](const xc7series::ConfigurationPacket &packet) {
return (packet.opcode() ==
xc7series::ConfigurationPacket::Opcode::Write) &&
(packet.address() ==
xc7series::ConfigurationRegister::IDCODE);
});
reader->begin(), reader->end(),
[](const xc7series::ConfigurationPacket& packet) {
return (packet.opcode() ==
xc7series::ConfigurationPacket::Opcode::Write) &&
(packet.address() ==
xc7series::ConfigurationRegister::IDCODE);
});
if (idcode_packet != reader->end()) {
if (idcode_packet->data().size() != 1) {
std::cerr << "Write to IDCODE with word_count != 1"
<< std::endl;
<< std::endl;
return 1;
}
std::cout << "0x" << std::hex << idcode_packet->data()[0]
<< std::endl;
<< std::endl;
}
return 0;
}
int main(int argc, char *argv[]) {
int main(int argc, char* argv[]) {
Action actions[] = {
{ "list_config_packets", ListConfigPackets },
{ "dump_debugbitstream_frame_addresses",
DumpDebugbitstreamFrameAddresses },
{ "get_device_id", GetDeviceId },
{"list_config_packets", ListConfigPackets},
{"dump_debugbitstream_frame_addresses",
DumpDebugbitstreamFrameAddresses},
{"get_device_id", GetDeviceId},
};
gflags::SetUsageMessage(
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (argc < 2) {
std::cerr << "ERROR: no command specified" << std::endl;
std::cerr << "Usage: " << argv[0]
<< "<command> <command_options>" << std::endl;
<< "<command> <command_options>" << std::endl;
return 1;
}
auto requested_action_str = argv[1];
auto requested_action = std::find_if(
std::begin(actions), std::end(actions),
[&](const Action& t) {
return t.name == requested_action_str; });
std::begin(actions), std::end(actions),
[&](const Action& t) { return t.name == requested_action_str; });
if (requested_action == std::end(actions)) {
std::cerr << "Unknown action: "
<< requested_action_str << std::endl;
std::cerr << "Unknown action: " << requested_action_str
<< std::endl;
return 1;
}

View File

@ -6,8 +6,8 @@
namespace xc7series = prjxray::xilinx::xc7series;
int main(int argc, char *argv[]) {
std::istream * input_stream = &std::cin;
int main(int argc, char* argv[]) {
std::istream* input_stream = &std::cin;
if (argc > 1) {
auto file_stream = std::ifstream(argv[1]);
if (file_stream) {
@ -16,27 +16,19 @@ int main(int argc, char *argv[]) {
}
for (uint32_t frame_address_raw;
(*input_stream) >> std::setbase(0) >> frame_address_raw;
) {
(*input_stream) >> std::setbase(0) >> frame_address_raw;) {
xc7series::FrameAddress frame_address(frame_address_raw);
std::cout << "["
<< std::hex << std::showbase << std::setw(10)
<< frame_address_raw
<< "] "
<< (frame_address.is_bottom_half_rows() ?
"BOTTOM" : "TOP")
<< " Row="
<< std::setw(2) << std::dec
<< static_cast<unsigned int>(frame_address.row_address())
<< " Column="
<< std::setw(2) << std::dec
<< frame_address.column_address()
<< " Minor="
<< std::setw(2) << std::dec
<< static_cast<unsigned int>(frame_address.minor_address())
<< " Type="
<< frame_address.block_type()
<< std::endl;
std::cout
<< "[" << std::hex << std::showbase << std::setw(10)
<< frame_address_raw << "] "
<< (frame_address.is_bottom_half_rows() ? "BOTTOM" : "TOP")
<< " Row=" << std::setw(2) << std::dec
<< static_cast<unsigned int>(frame_address.row_address())
<< " Column=" << std::setw(2) << std::dec
<< frame_address.column_address()
<< " Minor=" << std::setw(2) << std::dec
<< static_cast<unsigned int>(frame_address.minor_address())
<< " Type=" << frame_address.block_type() << std::endl;
}
return 0;

View File

@ -13,12 +13,11 @@
namespace xc7series = prjxray::xilinx::xc7series;
int main(int argc, char *argv[]) {
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "ERROR: no input specified" << std::endl;
std::cerr << "Usage: " << basename(argv[0])
<< " <bit_file>"
<< std::endl;
std::cerr << "Usage: " << basename(argv[0]) << " <bit_file>"
<< std::endl;
return 1;
}
@ -26,15 +25,14 @@ int main(int argc, char *argv[]) {
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
if (!in_file) {
std::cerr << "Unable to open bit file: " << in_file_name
<< std::endl;
<< std::endl;
return 1;
}
auto reader = xc7series::BitstreamReader::InitWithBytes(
in_file->as_bytes());
auto reader =
xc7series::BitstreamReader::InitWithBytes(in_file->as_bytes());
if (!reader) {
std::cerr << "Input doesn't look like a bitstream"
<< std::endl;
std::cerr << "Input doesn't look like a bitstream" << std::endl;
return 1;
}
@ -43,7 +41,7 @@ int main(int argc, char *argv[]) {
absl::optional<uint32_t> idcode;
for (auto packet : *reader) {
if (packet.opcode() !=
xc7series::ConfigurationPacket::Opcode::Write) {
xc7series::ConfigurationPacket::Opcode::Write) {
continue;
}
@ -51,13 +49,13 @@ int main(int argc, char *argv[]) {
xc7series::ConfigurationRegister::FDRI) {
found_fdri_write = true;
} else if ((packet.address() ==
xc7series::ConfigurationRegister::IDCODE) &&
packet.data().size() == 1) {
xc7series::ConfigurationRegister::IDCODE) &&
packet.data().size() == 1) {
idcode = packet.data()[0];
} else if (found_fdri_write &&
(packet.address() ==
xc7series::ConfigurationRegister::LOUT) &&
packet.data().size() == 1) {
(packet.address() ==
xc7series::ConfigurationRegister::LOUT) &&
packet.data().size() == 1) {
frame_addresses.push_back(packet.data()[0]);
}
}
@ -69,8 +67,8 @@ int main(int argc, char *argv[]) {
if (frame_addresses.empty()) {
std::cerr << "No LOUT writes found. Was "
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
<< std::endl;
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
<< std::endl;
return 1;
}
@ -80,17 +78,15 @@ int main(int argc, char *argv[]) {
std::vector<xc7series::ConfigurationFrameRange> ranges;
for (auto start_of_range = frame_addresses.begin();
start_of_range != frame_addresses.end();
) {
start_of_range != frame_addresses.end();) {
auto end_of_range = start_of_range;
while (end_of_range + 1 != frame_addresses.end() &&
*(end_of_range + 1) == *end_of_range + 1) {
++end_of_range;
}
ranges.push_back(
xc7series::ConfigurationFrameRange(*start_of_range,
*end_of_range+1));
ranges.push_back(xc7series::ConfigurationFrameRange(
*start_of_range, *end_of_range + 1));
start_of_range = ++end_of_range;
}

View File

@ -1,20 +1,23 @@
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <numeric>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <numeric>
#include <set>
#include <string>
#include <vector>
#include <absl/strings/str_cat.h>
#include <gflags/gflags.h>
DEFINE_int32(c, 4, "threshold under which candidates are output. set to -1 to output all.");
DEFINE_int32(
c,
4,
"threshold under which candidates are output. set to -1 to output all.");
DEFINE_bool(i, false, "add inverted tags");
DEFINE_int32(m, 0, "min number of set/cleared samples each");
DEFINE_int32(M, 0, "min number of set/cleared samples total");
@ -22,9 +25,9 @@ DEFINE_string(o, "", "set output file");
DEFINE_string(k, "", "set output mask file");
using std::map;
using std::string;
using std::tuple;
using std::vector;
using std::string;
int num_bits = 0, num_tags = 0;
map<string, int> bit_ids, tag_ids;
@ -76,51 +79,40 @@ struct bool_vec
}
};
#else
struct bool_vec
{
struct bool_vec {
vector<uint64_t> data;
bool_vec(int n = 0, bool initval = false) :
data((n+63)/64, initval ? ~uint64_t(0) : uint64_t(0))
{
for (int i = data.size()*64-1; i >= n; i--)
bool_vec(int n = 0, bool initval = false)
: data((n + 63) / 64, initval ? ~uint64_t(0) : uint64_t(0)) {
for (int i = data.size() * 64 - 1; i >= n; i--)
data[n / 64] &= ~(uint64_t(1) << (n % 64));
}
void set(int n)
{
if (int(data.size()*64) <= n)
data.resize((n+64) / 64);
void set(int n) {
if (int(data.size() * 64) <= n)
data.resize((n + 64) / 64);
data[n / 64] |= uint64_t(1) << (n % 64);
}
bool get(int n)
{
return (data[n / 64] >> (n % 64)) & 1;
}
bool get(int n) { return (data[n / 64] >> (n % 64)) & 1; }
void resize(int n)
{
data.resize((n+63) / 64);
}
void resize(int n) { data.resize((n + 63) / 64); }
int count()
{
int count() {
int sum = 0;
for (int i = 0; i < 64*int(data.size()); i++)
if (get(i)) sum++;
for (int i = 0; i < 64 * int(data.size()); i++)
if (get(i))
sum++;
return sum;
}
void apply_and(const bool_vec &other)
{
void apply_and(const bool_vec& other) {
assert(data.size() == other.data.size());
for (int i = 0; i < int(data.size()); i++)
data[i] &= other.data[i];
}
void apply_andc(const bool_vec &other)
{
void apply_andc(const bool_vec& other) {
assert(data.size() == other.data.size());
for (int i = 0; i < int(data.size()); i++)
data[i] &= ~other.data[i];
@ -134,19 +126,22 @@ map<string, segdata_t> segdata;
map<string, int> segnamecnt;
static inline bool_vec &segdata_bits(segdata_t &sd) { return std::get<0>(sd); }
static inline bool_vec &segdata_tags1(segdata_t &sd) { return std::get<1>(sd); }
static inline bool_vec &segdata_tags0(segdata_t &sd) { return std::get<2>(sd); }
static inline bool_vec& segdata_bits(segdata_t& sd) {
return std::get<0>(sd);
}
static inline bool_vec& segdata_tags1(segdata_t& sd) {
return std::get<1>(sd);
}
static inline bool_vec& segdata_tags0(segdata_t& sd) {
return std::get<2>(sd);
}
void read_input(std::istream &f, std::string filename)
{
void read_input(std::istream& f, std::string filename) {
string token;
segdata_t *segptr = nullptr;
segdata_t* segptr = nullptr;
while (f >> token)
{
if (token == "seg")
{
while (f >> token) {
if (token == "seg") {
f >> token;
token = filename + ":" + token;
while (segdata.count(token)) {
@ -162,8 +157,7 @@ void read_input(std::istream &f, std::string filename)
continue;
}
if (token == "bit")
{
if (token == "bit") {
assert(segptr != nullptr);
f >> token;
@ -173,14 +167,13 @@ void read_input(std::istream &f, std::string filename)
}
int bit_idx = bit_ids.at(token);
auto &bits = segdata_bits(*segptr);
auto& bits = segdata_bits(*segptr);
bits.set(bit_idx);
continue;
}
if (token == "tag")
{
if (token == "tag") {
assert(segptr != nullptr);
f >> token;
@ -194,13 +187,15 @@ void read_input(std::istream &f, std::string filename)
f >> token;
assert(token == "0" || token == "1");
auto &tags = token == "1" ? segdata_tags1(*segptr) : segdata_tags0(*segptr);
auto& tags = token == "1" ? segdata_tags1(*segptr)
: segdata_tags0(*segptr);
tags.set(tag_idx);
if (FLAGS_i)
{
auto &inv_tags = token == "1" ? segdata_tags0(*segptr) : segdata_tags1(*segptr);
if (FLAGS_i) {
auto& inv_tags = token == "1"
? segdata_tags0(*segptr)
: segdata_tags1(*segptr);
token = tag_ids_r.at(tag_idx) + "__INV";
@ -223,17 +218,16 @@ void read_input(std::istream &f, std::string filename)
// printf("Number of bits: %d\n", num_bits);
// printf("Number of tags: %d\n", num_tags);
for (auto &segdat : segdata) {
for (auto& segdat : segdata) {
segdata_bits(segdat.second).resize(num_bits);
segdata_tags1(segdat.second).resize(num_tags);
segdata_tags0(segdat.second).resize(num_tags);
}
}
int main(int argc, char **argv)
{
int main(int argc, char** argv) {
gflags::SetUsageMessage(
absl::StrCat("Usage: ", argv[0], " [options] file.."));
absl::StrCat("Usage: ", argv[0], " [options] file.."));
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (argc > 1) {
@ -253,7 +247,7 @@ int main(int argc, char **argv)
printf("#of bits: %d\n", num_bits);
printf("#of tags: %d\n", num_tags);
FILE *f = stdout;
FILE* f = stdout;
if (!FLAGS_o.empty()) {
f = fopen(FLAGS_o.c_str(), "w");
@ -269,14 +263,12 @@ int main(int argc, char **argv)
std::vector<std::string> out_lines;
for (int tag_idx = 0; tag_idx < num_tags; tag_idx++)
{
for (int tag_idx = 0; tag_idx < num_tags; tag_idx++) {
bool_vec mask(num_bits, true);
int count1 = 0, count0 = 0;
for (auto &segdat : segdata)
{
auto &sd = segdat.second;
for (auto& segdat : segdata) {
auto& sd = segdat.second;
bool tag1 = segdata_tags1(sd).get(tag_idx);
bool tag0 = segdata_tags0(sd).get(tag_idx);
@ -331,25 +323,28 @@ int main(int argc, char **argv)
int num_candidates = mask.count();
if (count0) {
min_candidates = std::min(min_candidates, num_candidates);
max_candidates = std::max(max_candidates, num_candidates);
min_candidates =
std::min(min_candidates, num_candidates);
max_candidates =
std::max(max_candidates, num_candidates);
avg_candidates += num_candidates;
cnt_candidates += 1;
}
if (FLAGS_c < 0 ||
(0 < num_candidates &&
num_candidates <= FLAGS_c)) {
(0 < num_candidates && num_candidates <= FLAGS_c)) {
std::vector<std::string> out_tags;
for (int bit_idx = 0; bit_idx < num_bits; bit_idx++)
if (mask.get(bit_idx))
out_tags.push_back(bit_ids_r.at(bit_idx));
out_tags.push_back(
bit_ids_r.at(bit_idx));
std::sort(out_tags.begin(), out_tags.end());
for (auto &tag : out_tags)
for (auto& tag : out_tags)
out_line += " " + tag;
} else {
char buffer[64];
snprintf(buffer, 64, " <%d candidates>", num_candidates);
snprintf(buffer, 64, " <%d candidates>",
num_candidates);
out_line += buffer;
}
@ -358,7 +353,7 @@ int main(int argc, char **argv)
std::sort(out_lines.begin(), out_lines.end());
for (auto &line : out_lines)
for (auto& line : out_lines)
fprintf(f, "%s\n", line.c_str());
if (cnt_candidates)
@ -383,4 +378,3 @@ int main(int argc, char **argv)
return 0;
}

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys, re
import sys
import re
database = dict()
database_r = dict()
@ -24,20 +25,23 @@ for arg in sys.argv[1:]:
database[key] = bits
database_r[bits] = key
def get_subsets(bits):
retval = list()
retval.append(bits)
for i in range(len(bits)):
for s in get_subsets(bits[i+1:]):
retval.append(bits[0:i] + s);
for s in get_subsets(bits[i + 1:]):
retval.append(bits[0:i] + s)
return retval
def check_subsets(bits):
for sub_bits in sorted(get_subsets(bits)):
if sub_bits != bits and sub_bits != ():
if sub_bits in database_r:
print("Warning: Entry %s %s is a subset of entry %s %s." % (database_r[sub_bits], sub_bits, database_r[bits], bits))
print("Warning: Entry %s %s is a subset of entry %s %s." %
(database_r[sub_bits], sub_bits, database_r[bits], bits))
for key, bits in database.items():
check_subsets(bits)

View File

@ -1,6 +1,8 @@
#/usr/bin/env python3
import sys, os, re
import sys
import os
import re
zero_db = [
"00_21 00_22 00_26 01_28|00_25 01_20 01_21 01_24",
@ -31,9 +33,11 @@ zero_db = [
"30_53 31_53 31_56 31_57",
]
def add_zero_bits(tile_type):
assert os.getenv("XRAY_DATABASE") in ["artix7", "kintex7"]
dbfile = "%s/%s/segbits_%s.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), tile_type)
dbfile = "%s/%s/segbits_%s.db" % (os.getenv("XRAY_DATABASE_DIR"),
os.getenv("XRAY_DATABASE"), tile_type)
new_lines = set()
llast = None
@ -84,9 +88,11 @@ def add_zero_bits(tile_type):
for line in sorted(new_lines):
print(line, file=f)
def update_mask(mask_db, *src_dbs):
bits = set()
mask_db_file = "%s/%s/mask_%s.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), mask_db)
mask_db_file = "%s/%s/mask_%s.db" % (
os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), mask_db)
if os.path.exists(mask_db_file):
with open(mask_db_file, "r") as f:
@ -97,7 +103,8 @@ def update_mask(mask_db, *src_dbs):
bits.add(line[1])
for src_db in src_dbs:
seg_db_file = "%s/%s/segbits_%s.db" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), src_db)
seg_db_file = "%s/%s/segbits_%s.db" % (
os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), src_db)
if not os.path.exists(seg_db_file):
continue
@ -114,6 +121,7 @@ def update_mask(mask_db, *src_dbs):
for bit in sorted(bits):
print("bit %s" % bit, file=f)
add_zero_bits("int_l")
add_zero_bits("int_r")
add_zero_bits("clbll_l")
@ -133,4 +141,3 @@ for k in range(5):
update_mask("bram%d_r" % k, "bram%d_r" % k, "int_r")
update_mask("dsp%d_l" % k, "dsp%d_l" % k, "int_l")
update_mask("dsp%d_r" % k, "dsp%d_r" % k, "int_r")

View File

@ -1,4 +1,7 @@
import os, json, re
import os
import json
import re
class segmaker:
def __init__(self, bitsfile):
@ -24,7 +27,8 @@ class segmaker:
if bit_wordidx not in self.bits[base_frame]:
self.bits[base_frame][bit_wordidx] = set()
self.bits[base_frame][bit_wordidx].add((bit_frame, bit_wordidx, bit_bitidx))
self.bits[base_frame][bit_wordidx].add(
(bit_frame, bit_wordidx, bit_bitidx))
def addtag(self, site, name, value):
if site not in self.tags:
@ -50,30 +54,35 @@ class segmaker:
segments = self.segments_by_type[segdata["type"]]
tile_type = tiledata["type"]
segname = "%s_%03d" % (segdata["baseaddr"][0][2:], segdata["baseaddr"][1])
segname = "%s_%03d" % (
segdata["baseaddr"][0][2:], segdata["baseaddr"][1])
def add_segbits():
if not segname in segments:
segments[segname] = { "bits": set(), "tags": dict() }
segments[segname] = {"bits": set(), "tags": dict()}
base_frame = int(segdata["baseaddr"][0][2:], 16)
for wordidx in range(segdata["baseaddr"][1], segdata["baseaddr"][1]+segdata["words"]):
for wordidx in range(segdata["baseaddr"][1], segdata["baseaddr"][1] + segdata["words"]):
if base_frame not in self.bits:
continue
if wordidx not in self.bits[base_frame]:
continue
for bit_frame, bit_wordidx, bit_bitidx in self.bits[base_frame][wordidx]:
bitname_frame = bit_frame - base_frame
bitname_bit = 32*(bit_wordidx - segdata["baseaddr"][1]) + bit_bitidx
bitname_bit = 32 * \
(bit_wordidx -
segdata["baseaddr"][1]) + bit_bitidx
if bitfilter is None or bitfilter(bitname_frame, bitname_bit):
bitname = "%02d_%02d" % (bitname_frame, bitname_bit)
bitname = "%02d_%02d" % (
bitname_frame, bitname_bit)
segments[segname]["bits"].add(bitname)
if tilename in self.tags:
add_segbits()
for name, value in self.tags[tilename].items():
tag = "%s.%s" % (re.sub("(LL|LM)?_[LR]$", "", tile_type), name)
tag = "%s.%s" % (
re.sub("(LL|LM)?_[LR]$", "", tile_type), name)
segments[segname]["tags"][tag] = value
for site in tiledata["sites"]:
@ -90,7 +99,8 @@ class segmaker:
assert 0
for name, value in self.tags[site].items():
tag = "%s.%s.%s" % (re.sub("(LL|LM)?_[LR]$", "", tile_type), sitekey, name)
tag = "%s.%s.%s" % (
re.sub("(LL|LM)?_[LR]$", "", tile_type), sitekey, name)
tag = tag.replace(".SLICEM.", ".")
tag = tag.replace(".SLICEL.", ".")
segments[segname]["tags"][tag] = value
@ -119,5 +129,5 @@ class segmaker:
for bitname in sorted(segdata["bits"]):
print("bit %s_%s" % (segname, bitname), file=f)
for tagname, tagval in sorted(segdata["tags"].items()):
print("tag %s_%s %d" % (segname, tagname, tagval), file=f)
print("tag %s_%s %d" %
(segname, tagname, tagval), file=f)

View File

@ -1,12 +1,17 @@
#!/usr/bin/env python3
import getopt, sys, os, json, re
import getopt
import sys
import os
import json
import re
flag_z = False
flag_b = False
flag_d = False
flag_D = False
def usage():
print("Usage: %s [options] <bits_file> [segments/tiles]" % sys.argv[0])
print("")
@ -24,6 +29,7 @@ def usage():
print("")
sys.exit(0)
try:
opts, args = getopt.getopt(sys.argv[1:], "zbdD")
except:
@ -67,6 +73,7 @@ with open(args[0], "r") as f:
segbitsdb = dict()
def get_database(segtype):
if segtype in segbitsdb:
return segbitsdb[segtype]
@ -85,16 +92,17 @@ def get_database(segtype):
return segbitsdb[segtype]
def handle_segment(segname):
if segname is None:
segframes = dict()
for segname, segdata in grid["segments"].items():
framebase = int(segdata["baseaddr"][0], 16)
for i in range(segdata["frames"]):
if (framebase+i) not in segframes:
segframes[framebase+i] = set()
if (framebase + i) not in segframes:
segframes[framebase + i] = set()
for j in range(segdata["baseaddr"][1], segdata["baseaddr"][1] + segdata["words"]):
segframes[framebase+i].add(j)
segframes[framebase + i].add(j)
for frame in sorted(bitdata.keys()):
for wordidx in sorted(bitdata[frame].keys()):
if frame in segframes and wordidx in segframes[frame]:
@ -151,14 +159,15 @@ def handle_segment(segname):
segbits = set()
segtags = set()
for frame in range(baseframe, baseframe+numframes):
for frame in range(baseframe, baseframe + numframes):
if frame not in bitdata:
continue
for wordidx in range(basewordidx, basewordidx+numwords):
for wordidx in range(basewordidx, basewordidx + numwords):
if wordidx not in bitdata[frame]:
continue
for bitidx in bitdata[frame][wordidx]:
segbits.add("%02d_%02d" % (frame - baseframe, 32*(wordidx - basewordidx) + bitidx))
segbits.add("%02d_%02d" % (frame - baseframe,
32 * (wordidx - basewordidx) + bitidx))
if flag_d or flag_D:
for entry in get_database(seginfo["type"]):
@ -185,6 +194,7 @@ def handle_segment(segname):
for tag in sorted(segtags):
print("tag %s" % tag)
if flag_b:
handle_segment(None)
@ -197,4 +207,3 @@ if len(args) == 1:
else:
for arg in args[1:]:
handle_segment(arg)

View File

@ -3,7 +3,9 @@
# Produces a complete database of wires in the ROI and their connections and tests if each
# routing node is a tree (i.e. fails with an error when a loop is found).
import os, sys, json
import os
import sys
import json
with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE")), "r") as f:
tilegrid = json.load(f)["tiles"]
@ -19,13 +21,16 @@ for tilename, tiledata in tilegrid.items():
key = (tiledata["grid_x"], tiledata["grid_y"])
grid[key] = tilename
def check_tileconn_entry(tilename, tiledata, entry, idx):
if idx == 0:
otheridx = 1
otherxy = (tiledata["grid_x"] + entry["grid_deltas"][0], tiledata["grid_y"] + entry["grid_deltas"][1])
otherxy = (tiledata["grid_x"] + entry["grid_deltas"]
[0], tiledata["grid_y"] + entry["grid_deltas"][1])
else:
otheridx = 0
otherxy = (tiledata["grid_x"] - entry["grid_deltas"][0], tiledata["grid_y"] - entry["grid_deltas"][1])
otherxy = (tiledata["grid_x"] - entry["grid_deltas"]
[0], tiledata["grid_y"] - entry["grid_deltas"][1])
if otherxy not in grid:
return
@ -37,7 +42,7 @@ def check_tileconn_entry(tilename, tiledata, entry, idx):
return
print(" Found relevant entry (%s %s %d %d): %s" % (entry["tile_types"][0], entry["tile_types"][1],
entry["grid_deltas"][0], entry["grid_deltas"][1], othertilename))
entry["grid_deltas"][0], entry["grid_deltas"][1], othertilename))
for pair in entry["wire_pairs"]:
wirename = "%s/%s" % (tilename, pair[idx])
@ -54,6 +59,7 @@ def check_tileconn_entry(tilename, tiledata, entry, idx):
wirepairs[otherwirename] = set()
wirepairs[otherwirename].add(wirename)
for tilename, tiledata in tilegrid.items():
print("Connecting wires in tile %s." % tilename)
for entry in tileconn:
@ -62,6 +68,7 @@ for tilename, tiledata in tilegrid.items():
if entry["tile_types"][1] == tiledata["type"]:
check_tileconn_entry(tilename, tiledata, entry, 1)
def check_wire(wire, source):
for next_wire in wirepairs[wire]:
if next_wire == source:
@ -73,10 +80,10 @@ def check_wire(wire, source):
remwires.remove(next_wire)
check_wire(next_wire, wire)
while len(remwires):
wire = remwires.pop()
print("Checking %s:" % wire)
check_wire(wire, None)
print("NO LOOP FOUND: OK")

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3
import os, sys, json
import os
import sys
import json
if len(sys.argv) != 3:
print("Usage example: python3 %s HCLK_R HCLK_SW6E3" % sys.argv[0])
@ -26,9 +28,11 @@ for entry in tileconn:
if wire_pair[this_idx] != sys.argv[2]:
continue
outdata.append((delta_x, delta_y, entry["tile_types"][other_idx], wire_pair[other_idx]))
max_tiletype_len = max(max_tiletype_len, len(entry["tile_types"][other_idx]))
outdata.append(
(delta_x, delta_y, entry["tile_types"][other_idx], wire_pair[other_idx]))
max_tiletype_len = max(max_tiletype_len, len(
entry["tile_types"][other_idx]))
for entry in outdata:
print("%3d %3d %-*s %s" % (entry[0], entry[1], max_tiletype_len, entry[2], entry[3]))
print("%3d %3d %-*s %s" %
(entry[0], entry[1], max_tiletype_len, entry[2], entry[3]))