mirror of https://github.com/openXC7/prjxray.git
Merge pull request #55 from kc8apf/xc7patch
FASM and xc7patch proof of concept using partial reconfig flow
This commit is contained in:
commit
79fa80c737
6
Makefile
6
Makefile
|
|
@ -8,6 +8,6 @@ go:
|
|||
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 yapf -p -i {} \;
|
||||
find . -name \*.cc -and -not -path './third_party/*' -and -not -path './.git/*' -exec $(CLANG_FORMAT) -style=file -i {} \;
|
||||
find . -name \*.h -and -not -path './third_party/*' -and -not -path './.git/*' -exec $(CLANG_FORMAT) -style=file -i {} \;
|
||||
find . -name \*.py -and -not -path './third_party/*' -and -not -path './.git/*' -exec yapf -p -i {} \;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ class BitstreamWriter {
|
|||
typedef std::array<uint32_t, 6> header_t;
|
||||
typedef std::vector<ConfigurationPacket> packets_t;
|
||||
// Only defined if a packet exists
|
||||
typedef absl::optional<absl::Span<uint32_t>> op_data_t;
|
||||
typedef absl::Span<uint32_t>::iterator data_iterator_t;
|
||||
typedef absl::optional<absl::Span<const uint32_t>> op_data_t;
|
||||
typedef absl::Span<const uint32_t>::iterator data_iterator_t;
|
||||
using itr_value_type = uint32_t;
|
||||
|
||||
class packet_iterator
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace xc7series {
|
|||
|
||||
class Configuration {
|
||||
public:
|
||||
using FrameMap = std::map<FrameAddress, absl::Span<uint32_t>>;
|
||||
using FrameMap = std::map<FrameAddress, absl::Span<const uint32_t>>;
|
||||
|
||||
template <typename Collection>
|
||||
static absl::optional<Configuration> InitWithPackets(
|
||||
|
|
@ -28,7 +28,7 @@ class Configuration {
|
|||
: part_(part) {
|
||||
for (auto& frame : *frames) {
|
||||
frames_[frame.first] =
|
||||
absl::Span<uint32_t>(frame.second);
|
||||
absl::Span<const uint32_t>(frame.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class ConfigurationPacket {
|
|||
ConfigurationPacket(unsigned int header_type,
|
||||
Opcode opcode,
|
||||
ConfigurationRegister address,
|
||||
const absl::Span<uint32_t>& data)
|
||||
const absl::Span<const uint32_t>& data)
|
||||
: header_type_(header_type),
|
||||
opcode_(opcode),
|
||||
address_(address),
|
||||
|
|
@ -47,13 +47,13 @@ class ConfigurationPacket {
|
|||
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<const uint32_t>& data() const { return data_; }
|
||||
|
||||
private:
|
||||
unsigned int header_type_;
|
||||
Opcode opcode_;
|
||||
ConfigurationRegister address_;
|
||||
absl::Span<uint32_t> data_;
|
||||
absl::Span<const uint32_t> data_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket& packet);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,11 @@ ConfigurationPacket::InitWithWords(absl::Span<uint32_t> words,
|
|||
// 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), {}};
|
||||
return {words.subspan(1),
|
||||
{{header_type,
|
||||
Opcode::NOP,
|
||||
ConfigurationRegister::CRC,
|
||||
{}}}};
|
||||
case 0x1: {
|
||||
Opcode opcode = static_cast<Opcode>(
|
||||
bit_field_get(words[0], 28, 27));
|
||||
|
|
@ -73,6 +77,10 @@ ConfigurationPacket::InitWithWords(absl::Span<uint32_t> words,
|
|||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket& packet) {
|
||||
if (packet.header_type() == 0x0) {
|
||||
return o << "[Zero-pad]" << std::endl;
|
||||
}
|
||||
|
||||
switch (packet.opcode()) {
|
||||
case ConfigurationPacket::Opcode::NOP:
|
||||
o << "[NOP]" << std::endl;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
# Top-level target for generating a programmable bitstream. Given a .fasm
|
||||
# file, calling make with the .fasm extension replaced with .hand_crafted.bit
|
||||
# will generate a bitstream that includes both the harness and the .fasm design
|
||||
# ready for programming to a board. For example, 'make
|
||||
# roi_noninv.hand_crafted.bit' will generate a bitstream that includes the
|
||||
# design from roi_noninv.fasm.
|
||||
%.hand_crafted.bit: init_sequence.bit %.no_headers.bin final_sequence.bin
|
||||
cat $^ > $@
|
||||
|
||||
%.no_headers.bin: %.patched.bin
|
||||
# WARNING: these values need to be tweaked if anything about the
|
||||
# Vivado-generated design changes.
|
||||
xxd -p -s 0x18 $< | xxd -r -p - $@
|
||||
|
||||
%.patched.bin: %.frm harness_routed.bit
|
||||
${XRAY_TOOLS_DIR}/xc7patch \
|
||||
--part_file ${XRAY_PART_YAML} \
|
||||
--bitstream_file harness_routed.bit \
|
||||
--frm_file $< \
|
||||
--output_file $@
|
||||
|
||||
# xc7patch currently only generates the actual frame writes which is
|
||||
# insufficient to program a device. Grab the initialization and finalization
|
||||
# sequences from the harness bitstream so they can be tacked on to the
|
||||
# xc7patch-generated bitstream to create a programmable bitstream.
|
||||
#
|
||||
# The offsets used below were determined by manually inspecting
|
||||
# harness_routed.bit with a hex editor. init_sequence.bit is the beginning of
|
||||
# the file until just before the actual frame data is sent via a write to FDRI.
|
||||
# final_sequence.bin is from just after the frame data write to the end of the
|
||||
# file. Note that final_sequence.bin normally includes at least one CRC check.
|
||||
# The sed command replaces any CRC checks with a Reset CRC command which is the
|
||||
# same behavior as setting BITSTREAM.GENERAL.CRC to Disabled. These offset
|
||||
# should not change unless you alter the bitstream format used (i.e. setting
|
||||
# BITSTREAM.GENERAL.DEBUGBITSTREAM or BITSTREAM.GENERAL.PERFRAMECRC to YES).
|
||||
init_sequence.bit: harness_routed.bit
|
||||
# WARNING: these values need to be tweaked if anything about the
|
||||
# Vivado-generated design changes.
|
||||
xxd -p -l 0x147 $< | xxd -r -p - $@
|
||||
|
||||
final_sequence.bin: harness_routed.bit
|
||||
# WARNING: these values need to be tweaked if anything about the
|
||||
# Vivado-generated design changes.
|
||||
xxd -p -s 0x216abf $< | \
|
||||
tr -d '\n' | \
|
||||
sed -e 's/30000001.\{8\}/3000800100000007/g' | \
|
||||
fold -w 40 | \
|
||||
xxd -r -p - $@
|
||||
|
||||
# Generate a suitable harness by using Vivado's partial reconfiguration
|
||||
# feature. roi_inv is used as a sample reconfiguration design as one is
|
||||
# required to generate a partial reconfiguration design.
|
||||
harness.dcp: harness.tcl top.v roi_base.v
|
||||
vivado -mode batch -source harness.tcl
|
||||
|
||||
roi_inv.dcp: roi_inv.tcl roi_inv.v
|
||||
vivado -mode batch -source roi_inv.tcl
|
||||
|
||||
roi_inv_routed.dcp roi_inv_w_harness_routed.dcp harness_routed.dcp: harness.dcp roi_inv.dcp roi_inv_routed.tcl
|
||||
vivado -mode batch -source roi_inv_routed.tcl
|
||||
|
||||
# Conversions between various formats.
|
||||
%.bit: %.dcp write_bitstream.tcl
|
||||
vivado -mode batch -source write_bitstream.tcl -tclargs $< $@
|
||||
|
||||
%.bits: %.bit
|
||||
${XRAY_BITREAD} -y -o $@ $<
|
||||
|
||||
# Extract only bits that are within the ROI.
|
||||
%.roi.bits: %.bit
|
||||
${XRAY_BITREAD} -F ${XRAY_ROI_FRAMES} -z -y -o $@ $<
|
||||
|
||||
%.segp: %.roi.bits
|
||||
${XRAY_SEGPRINT} -zd $< > $@
|
||||
|
||||
%.fasm: %.segp
|
||||
${XRAY_DIR}/tools/segprint2fasm.py $< $@
|
||||
|
||||
%.frm: %.fasm
|
||||
${XRAY_DIR}/tools/fasm2frame.py $< $@
|
||||
|
||||
# This format is a human-readable representation of the configuration packets
|
||||
# used to interact with 7-series chips over JTAG.
|
||||
%.packets: %.bit
|
||||
${XRAY_TOOLS_DIR}/bittool list_config_packets $< > $@
|
||||
|
||||
clean:
|
||||
rm -rf specimen_[0-9][0-9][0-9]/ seg_clblx.segbits vivado*.log vivado_*.str vivado*.jou design *.bits *.dcp *.bit design.txt .Xil
|
||||
rm -rf out_* *~
|
||||
rm -rf *.frm *.segp *.packets *.bin
|
||||
rm -rf harness_routed.fasm roi_inv_w_harness_routed.fasm
|
||||
rm -rf hd_visual
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# FASM Proof of Concept using Vivado Partial Reconfig flow
|
||||
|
||||
top.v is a top-level design that routes a variety of signal into a black-box
|
||||
region of interest (ROI). Vivado's Partial Reconfiguration flow (see UG909
|
||||
and UG947) is used to implement that design and obtain a bitstream that
|
||||
configures portions of the chip that are currently undocumented.
|
||||
|
||||
Designs that fit within the ROI are written in FASM and merged with the above
|
||||
harness into a bitstream with fasm2frame and xc7patch.
|
||||
|
||||
# Usage
|
||||
|
||||
make rules are provided for generating each step of the process so that
|
||||
intermediate forms can be analyzed. Assuming you have a .fasm file, invoking
|
||||
the %.hand\_crafted.bit rule will generate a merged bitstream:
|
||||
|
||||
```
|
||||
make foo.hand\_crafted.bit # reads foo.fasm
|
||||
```
|
||||
|
||||
# Using Vivado to generate .fasm
|
||||
|
||||
Vivado's Partial Reconfiguration flow can be used to synthesize and implement a
|
||||
design that is then converted to .fasm. The basic process is to write a module
|
||||
that _exactly_ matches the roi blackbox in the top-level design. Note that
|
||||
even the name of the module must match exactly. Once you have a design, the
|
||||
first step is to synthesize the design with -mode out\_of\_context:
|
||||
|
||||
```
|
||||
read_verilog <design>.v
|
||||
synth_design -mode out_of_context -top roi -part $::env(XRAY_PART)
|
||||
write_checkpoint -force <design>.dcp
|
||||
```
|
||||
|
||||
Next, implement that design within the harness. Run 'make harness\_routed.dcp'
|
||||
if it doesn't already exist. The following TCL will load the fully-routed
|
||||
harness, load your synthesized design, and generate a bitstream containing
|
||||
both:
|
||||
```
|
||||
open_checkpoint -force harness_routed.dcp
|
||||
read_checkpoint -cell <design>.dcp
|
||||
opt_design
|
||||
place_design
|
||||
route_design
|
||||
write_checkpoint -force <design>_routed.dcp
|
||||
write_bitstream -force <design>_routed.bit
|
||||
```
|
||||
|
||||
'make <design>\_routed.fasm' will run a sequence of tools to extract the bits
|
||||
that are inside the ROI and convert them to FASM. The resulting .fasm can be
|
||||
used to generate a marged bitstream using
|
||||
'make <design>\_routed.hand\_crafted.bit'. The resulting bitstream should be
|
||||
equivalent to <design>\_routed.bit.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
`ifndef DIN_N
|
||||
`define DIN_N 8
|
||||
`endif
|
||||
|
||||
`ifndef DOUT_N
|
||||
`define DOUT_N 8
|
||||
`endif
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
read_verilog top.v
|
||||
read_verilog roi_base.v
|
||||
|
||||
synth_design -top top -part $::env(XRAY_PART)
|
||||
write_checkpoint -force harness.dcp
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
//See README and tcl for more info
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
module roi(input clk,
|
||||
input [DIN_N-1:0] din, output [DOUT_N-1:0] dout);
|
||||
parameter DIN_N = `DIN_N;
|
||||
parameter DOUT_N = `DOUT_N;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
read_verilog roi_inv.v
|
||||
synth_design -mode out_of_context -top roi -part $::env(XRAY_PART)
|
||||
write_checkpoint -force roi_inv.dcp
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
//Connect the switches to the LEDs, inverting the signal in the ROI
|
||||
//Assumes # inputs = # outputs
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
module roi(input clk,
|
||||
input [DIN_N-1:0] din, output [DOUT_N-1:0] dout);
|
||||
parameter DIN_N = `DIN_N;
|
||||
parameter DOUT_N = `DOUT_N;
|
||||
wire [DIN_N-1:0] internal;
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
//CLK
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
reg clk_reg;
|
||||
always @(posedge clk) begin
|
||||
clk_reg <= clk_reg;
|
||||
end
|
||||
|
||||
//DIN
|
||||
for (i = 0; i < DIN_N; i = i+1) begin:ins
|
||||
//Very expensive inverter
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 #(
|
||||
.INIT(64'b01)
|
||||
) lut (
|
||||
.I0(din[i]),
|
||||
.I1(1'b0),
|
||||
.I2(1'b0),
|
||||
.I3(1'b0),
|
||||
.I4(1'b0),
|
||||
.I5(1'b0),
|
||||
.O(internal[i]));
|
||||
end
|
||||
|
||||
//DOUT
|
||||
for (i = 0; i < DOUT_N; i = i+1) begin:outs
|
||||
//Very expensive buffer
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 #(
|
||||
.INIT(64'b010)
|
||||
) lut (
|
||||
.I0(internal[i]),
|
||||
.I1(1'b0),
|
||||
.I2(1'b0),
|
||||
.I3(1'b0),
|
||||
.I4(1'b0),
|
||||
.I5(1'b0),
|
||||
.O(dout[i]));
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
open_checkpoint harness.dcp
|
||||
|
||||
create_pblock roi
|
||||
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
|
||||
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
|
||||
|
||||
set_property CFGBVS VCCO [current_design]
|
||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||
|
||||
# Number of package inputs going to ROI
|
||||
set DIN_N 8
|
||||
# Number of ROI outputs going to package
|
||||
set DOUT_N 8
|
||||
|
||||
set part $::env(XRAY_PART)
|
||||
set pincfg $::env(XRAY_PINCFG)
|
||||
|
||||
# Map of top level net names to IOB pin names
|
||||
array set net2pin [list]
|
||||
|
||||
# Create pin assignments based on what we are targetting
|
||||
# A50T I/O Bank 16 sequential layout
|
||||
if {$part eq "xc7a50tfgg484-1"} {
|
||||
# Partial list, expand as needed
|
||||
set bank_16 "F21 G22 G21 D21 E21 D22 E22 A21 B21 B22 C22 C20 D20 F20 F19 A19 A18"
|
||||
set banki 0
|
||||
|
||||
# CLK
|
||||
set pin [lindex $bank_16 $banki]
|
||||
incr banki
|
||||
set net2pin(clk) $pin
|
||||
|
||||
# DIN
|
||||
for {set i 0} {$i < $DIN_N} {incr i} {
|
||||
set pin [lindex $bank_16 $banki]
|
||||
incr banki
|
||||
set net2pin(din[$i]) $pin
|
||||
}
|
||||
|
||||
# DOUT
|
||||
for {set i 0} {$i < $DOUT_N} {incr i} {
|
||||
set pin [lindex $bank_16 $banki]
|
||||
incr banki
|
||||
set net2pin(dout[$i]) $pin
|
||||
}
|
||||
} elseif {$part eq "xc7a35tcsg324-1"} {
|
||||
# Arty A7 switch, button, and LED
|
||||
if {$pincfg eq "ARTY-A7-SWBUT"} {
|
||||
# https://reference.digilentinc.com/reference/programmable-logic/arty/reference-manual?redirect=1
|
||||
# 4 switches then 4 buttons
|
||||
set sw_but "A8 C11 C10 A10 D9 C9 B9 B8"
|
||||
# 4 LEDs then 4 RGB LEDs (green only)
|
||||
set leds "H5 J5 T9 T10 F6 J4 J2 H6"
|
||||
|
||||
# 100 MHz CLK onboard
|
||||
set pin "E3"
|
||||
set net2pin(clk) $pin
|
||||
|
||||
# DIN
|
||||
for {set i 0} {$i < $DIN_N} {incr i} {
|
||||
set pin [lindex $sw_but $i]
|
||||
set net2pin(din[$i]) $pin
|
||||
}
|
||||
|
||||
# DOUT
|
||||
for {set i 0} {$i < $DOUT_N} {incr i} {
|
||||
set pin [lindex $leds $i]
|
||||
set net2pin(dout[$i]) $pin
|
||||
}
|
||||
# Arty A7 pmod
|
||||
# Disabled per above
|
||||
} elseif {$pincfg eq "ARTY-A7-PMOD"} {
|
||||
# https://reference.digilentinc.com/reference/programmable-logic/arty/reference-manual?redirect=1
|
||||
set pmod_ja "G13 B11 A11 D12 D13 B18 A18 K16"
|
||||
set pmod_jb "E15 E16 D15 C15 J17 J18 K15 J15"
|
||||
set pmod_jc "U12 V12 V10 V11 U14 V14 T13 U13"
|
||||
|
||||
# CLK on Pmod JA
|
||||
set pin [lindex $pmod_ja 0]
|
||||
set net2pin(clk) $pin
|
||||
|
||||
# DIN on Pmod JB
|
||||
for {set i 0} {$i < $DIN_N} {incr i} {
|
||||
set pin [lindex $pmod_jb $i]
|
||||
set net2pin(din[$i]) $pin
|
||||
}
|
||||
|
||||
# DOUT on Pmod JC
|
||||
for {set i 0} {$i < $DOUT_N} {incr i} {
|
||||
set pin [lindex $pmod_jc $i]
|
||||
set net2pin(dout[$i]) $pin
|
||||
}
|
||||
} else {
|
||||
error "Unsupported config $pincfg"
|
||||
}
|
||||
} elseif {$part eq "xc7a35tcpg236-1"} {
|
||||
if {$pincfg eq "BASYS3-SWBUT"} {
|
||||
# https://raw.githubusercontent.com/Digilent/digilent-xdc/master/Basys-3-Master.xdc
|
||||
|
||||
# Slide switches
|
||||
set sws "V17 V16 W16 W17 W15 V15 W14 W13 V2 T3 T2 R3 W2 U1 T1 R2"
|
||||
set leds "U16 E19 U19 V19 W18 U15 U14 V14 V13 V3 W3 U3 P3 N3 P1 L1"
|
||||
|
||||
# 100 MHz CLK onboard
|
||||
set pin "W5"
|
||||
set net2pin(clk) $pin
|
||||
|
||||
# DIN
|
||||
for {set i 0} {$i < $DIN_N} {incr i} {
|
||||
set pin [lindex $sws $i]
|
||||
set net2pin(din[$i]) $pin
|
||||
}
|
||||
|
||||
# DOUT
|
||||
for {set i 0} {$i < $DOUT_N} {incr i} {
|
||||
set pin [lindex $leds $i]
|
||||
set net2pin(dout[$i]) $pin
|
||||
}
|
||||
} else {
|
||||
error "Unsupported config $pincfg"
|
||||
}
|
||||
} else {
|
||||
error "Pins: unsupported part $part"
|
||||
}
|
||||
|
||||
# Now actually apply the pin definitions
|
||||
puts "Applying pin definitions"
|
||||
foreach {net pin} [array get net2pin] {
|
||||
puts " Net $net to pin $pin"
|
||||
set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" [get_ports $net]
|
||||
}
|
||||
|
||||
set_property HD.RECONFIGURABLE TRUE [get_cells roi]
|
||||
|
||||
read_checkpoint -cell roi roi_inv.dcp
|
||||
|
||||
opt_design
|
||||
place_design
|
||||
route_design
|
||||
|
||||
write_checkpoint -force roi_inv_w_harness_routed.dcp
|
||||
|
||||
# Routed design of roi cell only
|
||||
write_checkpoint -force -cell roi roi_inv_routed.dcp
|
||||
|
||||
# Replace roi cell with a black box and write the rest of the design
|
||||
update_design -cell roi -black_box
|
||||
lock_design -level routing
|
||||
write_checkpoint -force harness_routed.dcp
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
INT_L_X10Y107.CENTER_INTER_L.SE6BEG0 NN6END0
|
||||
INT_L_X10Y104.CENTER_INTER_L.WL1BEG0 NW2END2
|
||||
INT_L_X10Y103.CENTER_INTER_L.EL1BEG0 NR1END1
|
||||
INT_L_X10Y103.CENTER_INTER_L.EL1BEG_N3 NW2END0
|
||||
INT_L_X10Y103.CENTER_INTER_L.FAN_ALT4 NR1END0
|
||||
INT_L_X10Y103.CENTER_INTER_L.NE2BEG3 NL1BEG_N3
|
||||
INT_L_X10Y103.CENTER_INTER_L.NL1BEG_N3 NL1END0
|
||||
INT_L_X10Y103.CENTER_INTER_L.SE2BEG2 EL1END2
|
||||
INT_L_X10Y103.CENTER_INTER_L.WW2BEG2 WL1END2
|
||||
CLBLM_L_X10Y102.SLICE_X13Y102.ALUT.INIT[01] 1
|
||||
CLBLM_L_X10Y102.SLICE_X13Y102.BLUT.INIT[01] 1
|
||||
CLBLM_L_X10Y102.SLICE_X12Y102.ALUT.INIT[01] 1
|
||||
CLBLM_L_X10Y102.SLICE_X12Y102.BLUT.INIT[01] 1
|
||||
INT_L_X10Y102.CENTER_INTER_L.BYP_ALT5 NN2END2
|
||||
INT_L_X10Y102.CENTER_INTER_L.EE2BEG2 NL1END2
|
||||
INT_L_X10Y102.CENTER_INTER_L.EL1BEG_N3 NL1END0
|
||||
INT_L_X10Y102.CENTER_INTER_L.GFAN0 GND_WIRE
|
||||
INT_L_X10Y102.CENTER_INTER_L.GFAN1 GND_WIRE
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L0 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L1 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L10 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L11 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L12 GFAN1
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L13 GFAN1
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L14 NL1BEG_N3
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L15 FAN_BOUNCE_S3_4
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L16 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L17 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L18 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L19 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L2 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L24 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L25 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L26 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L27 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L3 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L4 GFAN1
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L5 GFAN1
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L6 WR1END3
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L7 BYP_BOUNCE5
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L8 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.IMUX_L9 GFAN0
|
||||
INT_L_X10Y102.CENTER_INTER_L.NL1BEG0 LOGIC_OUTS_L9
|
||||
INT_L_X10Y102.CENTER_INTER_L.NL1BEG_N3 LOGIC_OUTS_L8
|
||||
INT_L_X10Y102.CENTER_INTER_L.NR1BEG0 LOGIC_OUTS_L12
|
||||
INT_L_X10Y102.CENTER_INTER_L.NR1BEG1 LOGIC_OUTS_L13
|
||||
INT_L_X10Y102.CENTER_INTER_L.SE2BEG2 EL1END2
|
||||
INT_L_X10Y102.CENTER_INTER_L.SR1BEG2 WL1END1
|
||||
INT_L_X10Y102.CENTER_INTER_L.SW2BEG3 WL1END3
|
||||
INT_L_X10Y102.CENTER_INTER_L.WW2BEG2 WL1END2
|
||||
CLBLM_L_X10Y101.SLICE_X13Y101.ALUT.INIT[01] 1
|
||||
CLBLM_L_X10Y101.SLICE_X13Y101.BLUT.INIT[01] 1
|
||||
CLBLM_L_X10Y101.SLICE_X12Y101.ALUT.INIT[01] 1
|
||||
CLBLM_L_X10Y101.SLICE_X12Y101.BLUT.INIT[01] 1
|
||||
INT_L_X10Y101.CENTER_INTER_L.BYP_ALT3 NL1BEG_N3
|
||||
INT_L_X10Y101.CENTER_INTER_L.BYP_ALT4 NW2END1
|
||||
INT_L_X10Y101.CENTER_INTER_L.ER1BEG2 LOGIC_OUTS_L13
|
||||
INT_L_X10Y101.CENTER_INTER_L.GFAN0 GND_WIRE
|
||||
INT_L_X10Y101.CENTER_INTER_L.GFAN1 GND_WIRE
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L0 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L1 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L10 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L11 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L12 GFAN1
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L13 GFAN1
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L14 SR1END2
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L15 BYP_BOUNCE3
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L16 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L17 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L18 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L19 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L2 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L24 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L25 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L26 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L27 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L3 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L4 GFAN1
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L5 GFAN1
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L6 BYP_BOUNCE4
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L7 NW2END_S0_0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L8 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.IMUX_L9 GFAN0
|
||||
INT_L_X10Y101.CENTER_INTER_L.LV_L18 SR1BEG_S0
|
||||
INT_L_X10Y101.CENTER_INTER_L.NE2BEG1 NR1END1
|
||||
INT_L_X10Y101.CENTER_INTER_L.NE2BEG3 NN6END3
|
||||
INT_L_X10Y101.CENTER_INTER_L.NL1BEG0 LOGIC_OUTS_L9
|
||||
INT_L_X10Y101.CENTER_INTER_L.NL1BEG2 WL1END2
|
||||
INT_L_X10Y101.CENTER_INTER_L.NL1BEG_N3 LOGIC_OUTS_L8
|
||||
INT_L_X10Y101.CENTER_INTER_L.NN6BEG0 LOGIC_OUTS_L12
|
||||
INT_L_X10Y101.CENTER_INTER_L.SE2BEG2 EE2END2
|
||||
INT_L_X10Y101.CENTER_INTER_L.SR1BEG_S0 WL1END3
|
||||
CLBLM_L_X10Y100.SLICE_X13Y100.ALUT.INIT[01] 1
|
||||
CLBLM_L_X10Y100.SLICE_X13Y100.BLUT.INIT[01] 1
|
||||
CLBLM_L_X10Y100.SLICE_X12Y100.ALUT.INIT[01] 1
|
||||
INT_L_X10Y100.CENTER_INTER_L.BYP_ALT1 LOGIC_OUTS_L8
|
||||
INT_L_X10Y100.CENTER_INTER_L.BYP_ALT2 BYP_BOUNCE1
|
||||
INT_L_X10Y100.CENTER_INTER_L.BYP_ALT3 NL1BEG_N3
|
||||
INT_L_X10Y100.CENTER_INTER_L.EE2BEG3 NN6END3
|
||||
INT_L_X10Y100.CENTER_INTER_L.ER1BEG1 SR1BEG_S0
|
||||
INT_L_X10Y100.CENTER_INTER_L.GFAN0 GND_WIRE
|
||||
INT_L_X10Y100.CENTER_INTER_L.GFAN1 GND_WIRE
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L0 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L1 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L10 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L11 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L13 GFAN1
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L14 BYP_BOUNCE2
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L16 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L19 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L2 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L25 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L26 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L3 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L4 GFAN1
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L5 GFAN1
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L6 SW2END2
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L7 BYP_BOUNCE3
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L8 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.IMUX_L9 GFAN0
|
||||
INT_L_X10Y100.CENTER_INTER_L.NE2BEG0 LOGIC_OUTS_L12
|
||||
INT_L_X10Y100.CENTER_INTER_L.NE2BEG3 NE6END3
|
||||
INT_L_X10Y100.CENTER_INTER_L.NL1BEG_N3 WL1END_N1_3
|
||||
INT_L_X10Y100.CENTER_INTER_L.NN2BEG2 WL1END1
|
||||
INT_L_X10Y100.CENTER_INTER_L.NR1BEG1 LOGIC_OUTS_L9
|
||||
INT_L_X10Y100.CENTER_INTER_L.SR1BEG_S0 WL1END3
|
||||
INT_R_X11Y104.CENTER_INTER_R.SL1BEG3 NE2END3
|
||||
INT_R_X11Y103.CENTER_INTER_R.NW2BEG2 NN2END2
|
||||
INT_R_X11Y103.CENTER_INTER_R.SL1BEG0 EL1END0
|
||||
INT_R_X11Y103.CENTER_INTER_R.WL1BEG2 SL1END3
|
||||
INT_R_X11Y103.CENTER_INTER_R.WL1BEG_N3 WR1END1
|
||||
CLBLM_R_X11Y102.SLICE_X14Y102.ALUT.INIT[01] 1
|
||||
CLBLM_R_X11Y102.SLICE_X14Y102.BLUT.INIT[01] 1
|
||||
INT_R_X11Y102.CENTER_INTER_R.EL1BEG0 LOGIC_OUTS13
|
||||
INT_R_X11Y102.CENTER_INTER_R.GFAN0 GND_WIRE
|
||||
INT_R_X11Y102.CENTER_INTER_R.GFAN1 GND_WIRE
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX1 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX11 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX12 GFAN1
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX15 EL1END3
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX17 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX18 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX2 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX24 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX27 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX4 GFAN1
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX7 WR1END3
|
||||
INT_R_X11Y102.CENTER_INTER_R.IMUX8 GFAN0
|
||||
INT_R_X11Y102.CENTER_INTER_R.NW2BEG0 LOGIC_OUTS12
|
||||
INT_R_X11Y102.CENTER_INTER_R.SE2BEG1 NE2END1
|
||||
INT_R_X11Y102.CENTER_INTER_R.SL1BEG2 SE2END2
|
||||
INT_R_X11Y102.CENTER_INTER_R.SL1BEG3 NE2END3
|
||||
INT_R_X11Y102.CENTER_INTER_R.WL1BEG1 NW2END3
|
||||
INT_R_X11Y102.CENTER_INTER_R.WL1BEG2 WL1END3
|
||||
INT_R_X11Y102.CENTER_INTER_R.WL1BEG_N3 SL1END0
|
||||
INT_R_X11Y102.CENTER_INTER_R.WR1BEG3 NR1END2
|
||||
CLBLM_R_X11Y101.SLICE_X14Y101.ALUT.INIT[01] 1
|
||||
CLBLM_R_X11Y101.SLICE_X14Y101.AMUX.O6 1
|
||||
CLBLM_R_X11Y101.SLICE_X14Y101.BLUT.INIT[01] 1
|
||||
INT_R_X11Y101.CENTER_INTER_R.EE2BEG2 ER1END2
|
||||
INT_R_X11Y101.CENTER_INTER_R.EL1BEG0 LOGIC_OUTS13
|
||||
INT_R_X11Y101.CENTER_INTER_R.GFAN0 GND_WIRE
|
||||
INT_R_X11Y101.CENTER_INTER_R.GFAN1 GND_WIRE
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX1 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX11 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX12 GFAN1
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX15 EL1END3
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX17 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX18 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX2 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX24 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX27 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX4 GFAN1
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX7 NR1END3
|
||||
INT_R_X11Y101.CENTER_INTER_R.IMUX8 GFAN0
|
||||
INT_R_X11Y101.CENTER_INTER_R.NN2BEG2 LOGIC_OUTS20
|
||||
INT_R_X11Y101.CENTER_INTER_R.NR1BEG2 SE2END2
|
||||
INT_R_X11Y101.CENTER_INTER_R.NW2BEG0 NE2END0
|
||||
INT_R_X11Y101.CENTER_INTER_R.SL1BEG3 NE2END3
|
||||
INT_R_X11Y101.CENTER_INTER_R.SR1BEG_S0 SL1END3
|
||||
INT_R_X11Y101.CENTER_INTER_R.SW2BEG2 SL1END2
|
||||
INT_R_X11Y101.CENTER_INTER_R.WL1BEG2 WR1END_S1_0
|
||||
INT_R_X11Y101.CENTER_INTER_R.WL1BEG_N3 SR1BEG_S0
|
||||
INT_R_X11Y101.CENTER_INTER_R.WW2BEG0 WL1END0
|
||||
INT_R_X11Y101.CENTER_INTER_R.WW2BEG1 WL1END1
|
||||
CLBLM_R_X11Y100.SLICE_X14Y100.ALUT.INIT[01] 1
|
||||
INT_R_X11Y100.CENTER_INTER_R.BYP_ALT5 ER1END1
|
||||
INT_R_X11Y100.CENTER_INTER_R.GFAN0 GND_WIRE
|
||||
INT_R_X11Y100.CENTER_INTER_R.GFAN1 GND_WIRE
|
||||
INT_R_X11Y100.CENTER_INTER_R.IMUX1 GFAN0
|
||||
INT_R_X11Y100.CENTER_INTER_R.IMUX11 GFAN0
|
||||
INT_R_X11Y100.CENTER_INTER_R.IMUX2 GFAN0
|
||||
INT_R_X11Y100.CENTER_INTER_R.IMUX4 GFAN1
|
||||
INT_R_X11Y100.CENTER_INTER_R.IMUX7 BYP_BOUNCE5
|
||||
INT_R_X11Y100.CENTER_INTER_R.IMUX8 GFAN0
|
||||
INT_R_X11Y100.CENTER_INTER_R.NL1BEG_N3 LOGIC_OUTS12
|
||||
INT_R_X11Y100.CENTER_INTER_R.NR1BEG3 NL1BEG_N3
|
||||
INT_R_X11Y100.CENTER_INTER_R.NW2BEG1 WL1END0
|
||||
INT_R_X11Y100.CENTER_INTER_R.SR1BEG_S0 SL1END3
|
||||
INT_R_X11Y100.CENTER_INTER_R.WL1BEG1 SE2END2
|
||||
INT_R_X11Y100.CENTER_INTER_R.WL1BEG_N3 SR1BEG_S0
|
||||
INT_L_X12Y103.CENTER_INTER_L.WL1BEG_N3 SE6END0
|
||||
INT_L_X12Y103.CENTER_INTER_L.WR1BEG1 NR1END0
|
||||
INT_L_X12Y102.CENTER_INTER_L.NR1BEG0 EL1END0
|
||||
INT_L_X12Y102.CENTER_INTER_L.WR1BEG3 EE2END2
|
||||
INT_L_X12Y101.CENTER_INTER_L.NW2BEG3 NR1END3
|
||||
INT_L_X12Y101.CENTER_INTER_L.SE2BEG0 EL1END0
|
||||
INT_L_X12Y101.CENTER_INTER_L.WL1BEG0 SE2END1
|
||||
INT_L_X12Y101.CENTER_INTER_L.WL1BEG1 WR1END3
|
||||
INT_L_X12Y101.CENTER_INTER_L.WR1BEG_S0 NE6END3
|
||||
INT_L_X12Y100.CENTER_INTER_L.EL1BEG2 NE6END3
|
||||
INT_L_X12Y100.CENTER_INTER_L.LV_L18 WR1END0
|
||||
INT_L_X12Y100.CENTER_INTER_L.NR1BEG3 EE2END3
|
||||
INT_L_X12Y100.CENTER_INTER_L.SW6BEG3 LV_L18
|
||||
INT_L_X12Y100.CENTER_INTER_L.WL1BEG0 WR1END2
|
||||
INT_R_X13Y101.CENTER_INTER_R.WR1BEG3 EE2END2
|
||||
INT_R_X13Y100.CENTER_INTER_R.SL1BEG2 EL1END2
|
||||
INT_R_X13Y100.CENTER_INTER_R.WL1BEG_N3 SE2END0
|
||||
INT_R_X13Y100.CENTER_INTER_R.WR1BEG2 NR1END1
|
||||
INT_L_X16Y100.CENTER_INTER_L.ER1BEG1 SR1BEG_S0
|
||||
INT_L_X16Y100.CENTER_INTER_L.SR1BEG_S0 WL1END3
|
||||
INT_R_X17Y101.CENTER_INTER_R.WL1BEG_N3 WW2END0
|
||||
CLBLL_R_X17Y100.SLICE_X27Y100.AFF.DMUX.AX 1
|
||||
CLBLL_R_X17Y100.SLICE_X27Y100.AFF.ZINI 1
|
||||
CLBLL_R_X17Y100.SLICE_X27Y100.AFF.ZRST 1
|
||||
CLBLL_R_X17Y100.SLICE_X27Y100.FFSYNC 1
|
||||
INT_R_X17Y100.CENTER_INTER_R.BYP_ALT0 LOGIC_OUTS0
|
||||
INT_R_X17Y100.CENTER_INTER_R.CLK0 ER1END1
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
//See README and tcl for more info
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
module top(input wire clk,
|
||||
input [DIN_N-1:0] din, output [DOUT_N-1:0] dout);
|
||||
parameter DIN_N = `DIN_N;
|
||||
parameter DOUT_N = `DOUT_N;
|
||||
|
||||
roi #(.DIN_N(DIN_N), .DOUT_N(DOUT_N)) roi (
|
||||
.clk(clk),
|
||||
.din(din), .dout(dout));
|
||||
endmodule
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
open_checkpoint [lindex $argv 0]
|
||||
|
||||
# Disabling CRC just replaces the CRC register writes with Reset CRC commands.
|
||||
# This seems to work via JTAG as it works in combination with PERFRAMECRC
|
||||
# either when applied via Vivado (this setting) or by manually patching the
|
||||
# bitstream later.
|
||||
#
|
||||
set_property BITSTREAM.GENERAL.CRC Disable [current_design]
|
||||
|
||||
# Debug bitstreams write to LOUT which is only valid on serial master/slave
|
||||
# programming methods. If those are replaced with NOPs, Reset CRC commands, or
|
||||
# removed entirely, the bitstream will program (DONE light goes active) but the
|
||||
# configuration doesn't start. The JTAG status register shows BAD_PACKET_ERROR
|
||||
# when this happens. I'm guessing that the individual frame writes require the
|
||||
# PERFRAMECRC approach to work at all via JTAG.
|
||||
#
|
||||
#set_property BITSTREAM.GENERAL.DEBUGBITSTREAM YES [current_design]
|
||||
|
||||
# PERFRAMECRC bitstreams can be directly loaded via JTAG. They also use an
|
||||
# undocumented bit to disable autoincrement which seems to be required if doing
|
||||
# individual frame writes instead of a bulk write. The CRC chceks after each
|
||||
# frame are _required_ for this bitstream to program.
|
||||
#
|
||||
#set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||
|
||||
|
||||
write_bitstream -force [lindex $argv 1]
|
||||
|
|
@ -17,3 +17,10 @@ target_link_libraries(gen_part_base_yaml
|
|||
libprjxray
|
||||
yaml-cpp
|
||||
)
|
||||
|
||||
add_executable(xc7patch xc7patch.cc)
|
||||
target_link_libraries(xc7patch
|
||||
absl::strings
|
||||
gflags
|
||||
libprjxray
|
||||
)
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ def run(f_in, f_out, sparse=False, debug=False):
|
|||
return '%s.%s.%s' % (tilej['type'], suffix, value)
|
||||
|
||||
tile2dbkey = {
|
||||
'CLBLL_L': clb2dbkey,
|
||||
'CLBLL_R': clb2dbkey,
|
||||
'CLBLM_L': clb2dbkey,
|
||||
'CLBLM_R': clb2dbkey,
|
||||
'INT_L': int2dbkey,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ def tag2fasm(grid, seg, tag):
|
|||
which = m.group(1)
|
||||
value = m.group(2)
|
||||
site = {
|
||||
'clbll_l': 'CENTER_INTER_L',
|
||||
'clbll_r': 'CENTER_INTER_R',
|
||||
'clblm_l': 'CENTER_INTER_L',
|
||||
'clblm_r': 'CENTER_INTER_R',
|
||||
'hclk_l': 'HCLK_L',
|
||||
|
|
@ -56,6 +58,8 @@ def tag2fasm(grid, seg, tag):
|
|||
raise Exception("Couldn't find tile type %s" % tile_type)
|
||||
|
||||
tag2asm = {
|
||||
'CLBLL_L': clbf,
|
||||
'CLBLL_R': clbf,
|
||||
'CLBLM_L': clbf,
|
||||
'CLBLM_R': clbf,
|
||||
'INT_L': intf,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,210 @@
|
|||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <absl/strings/str_split.h>
|
||||
#include <gflags/gflags.h>
|
||||
#include <prjxray/memory_mapped_file.h>
|
||||
#include <prjxray/xilinx/xc7series/bitstream_reader.h>
|
||||
#include <prjxray/xilinx/xc7series/bitstream_writer.h>
|
||||
#include <prjxray/xilinx/xc7series/configuration.h>
|
||||
#include <prjxray/xilinx/xc7series/part.h>
|
||||
|
||||
DEFINE_string(part_file, "", "Definition file for target 7-series part");
|
||||
DEFINE_string(bitstream_file,
|
||||
"",
|
||||
"Initial bitstream to which the deltas are applied.");
|
||||
DEFINE_string(
|
||||
frm_file,
|
||||
"",
|
||||
"File containing a list of frame deltas to be applied to the base "
|
||||
"bitstream. Each line in the file is of the form: "
|
||||
"<frame_address> <word1>,...,<word101>.");
|
||||
DEFINE_string(output_file, "", "Write patched bitsteam to file");
|
||||
|
||||
namespace xc7series = prjxray::xilinx::xc7series;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::SetUsageMessage(argv[0]);
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
auto part = xc7series::Part::FromFile(FLAGS_part_file);
|
||||
if (!part) {
|
||||
std::cerr << "Part file not found or invalid" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto bitstream_file =
|
||||
prjxray::MemoryMappedFile::InitWithFile(FLAGS_bitstream_file);
|
||||
if (!bitstream_file) {
|
||||
std::cerr << "Can't open base bitstream file: "
|
||||
<< FLAGS_bitstream_file << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto bitstream_reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
bitstream_file->as_bytes());
|
||||
if (!bitstream_reader) {
|
||||
std::cout
|
||||
<< "Bitstream does not appear to be a 7-series bitstream!"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto bitstream_config =
|
||||
xc7series::Configuration::InitWithPackets(*part, *bitstream_reader);
|
||||
if (!bitstream_config) {
|
||||
std::cerr << "Bitstream does not appear to be for this part"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Copy the base frames to a mutable collection
|
||||
std::map<xc7series::FrameAddress, std::vector<uint32_t>> frames;
|
||||
for (auto& frame_val : bitstream_config->frames()) {
|
||||
auto& cur_frame = frames[frame_val.first];
|
||||
|
||||
std::copy(frame_val.second.begin(), frame_val.second.end(),
|
||||
std::back_inserter(cur_frame));
|
||||
}
|
||||
|
||||
// Apply the deltas.
|
||||
std::ifstream frm_file(FLAGS_frm_file);
|
||||
if (!frm_file) {
|
||||
std::cerr << "Unable to open frm file: " << FLAGS_frm_file
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string frm_line;
|
||||
while (std::getline(frm_file, frm_line)) {
|
||||
if (frm_line[0] == '#')
|
||||
continue;
|
||||
|
||||
std::pair<std::string, std::string> frame_delta =
|
||||
absl::StrSplit(frm_line, ' ');
|
||||
|
||||
uint32_t frame_address =
|
||||
std::stoul(frame_delta.first, nullptr, 16);
|
||||
|
||||
auto& frame_data = frames[frame_address];
|
||||
frame_data.resize(101);
|
||||
|
||||
std::vector<std::string> frame_data_strings =
|
||||
absl::StrSplit(frame_delta.second, ',');
|
||||
if (frame_data_strings.size() != 101) {
|
||||
std::cerr << "Frame " << std::hex << frame_address
|
||||
<< ": found " << std::dec
|
||||
<< frame_data_strings.size()
|
||||
<< "words instead of 101";
|
||||
continue;
|
||||
};
|
||||
|
||||
std::transform(frame_data_strings.begin(),
|
||||
frame_data_strings.end(), frame_data.begin(),
|
||||
[](const std::string& val) -> uint32_t {
|
||||
return std::stoul(val, nullptr, 16);
|
||||
});
|
||||
|
||||
uint32_t ecc = 0;
|
||||
for (size_t ii = 0; ii < frame_data.size(); ++ii) {
|
||||
uint32_t word = frame_data[ii];
|
||||
uint32_t offset = ii * 32;
|
||||
if (ii > 0x25) {
|
||||
offset += 0x1360;
|
||||
} else if (ii > 0x6) {
|
||||
offset += 0x1340;
|
||||
} else {
|
||||
offset += 0x1320;
|
||||
}
|
||||
|
||||
// Mask out where the ECC should be.
|
||||
if (ii == 0x32) {
|
||||
word &= 0xFFFFE000;
|
||||
}
|
||||
|
||||
for (int jj = 0; jj < 32; ++jj) {
|
||||
if ((word & 1) == 1) {
|
||||
ecc ^= offset + jj;
|
||||
}
|
||||
word >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t v = ecc & 0xFFF;
|
||||
v ^= v >> 8;
|
||||
v ^= v >> 4;
|
||||
v ^= v >> 2;
|
||||
v ^= v >> 1;
|
||||
ecc ^= (v & 1) << 12;
|
||||
|
||||
// Replace the old ECC with the new.
|
||||
frame_data[0x32] &= 0xFFFFE000;
|
||||
frame_data[0x32] |= (ecc & 0x1FFF);
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (auto& frame : frames) {
|
||||
std::cout << "0x" << std::hex
|
||||
<< static_cast<uint32_t>(frame.first) << " ";
|
||||
|
||||
for (auto& word : frame.second) {
|
||||
std::cout << "0x" << std::hex << word << ",";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
std::vector<xc7series::ConfigurationPacket> out_packets;
|
||||
|
||||
// Generate a single type 2 packet that writes everything at once.
|
||||
std::vector<uint32_t> packet_data;
|
||||
for (auto& frame : frames) {
|
||||
std::copy(frame.second.begin(), frame.second.end(),
|
||||
std::back_inserter(packet_data));
|
||||
|
||||
auto next_address = part->GetNextFrameAddress(frame.first);
|
||||
if (next_address &&
|
||||
(next_address->block_type() != frame.first.block_type() ||
|
||||
next_address->is_bottom_half_rows() !=
|
||||
frame.first.is_bottom_half_rows() ||
|
||||
next_address->row() != frame.first.row())) {
|
||||
packet_data.insert(packet_data.end(), 202, 0);
|
||||
}
|
||||
}
|
||||
packet_data.insert(packet_data.end(), 202, 0);
|
||||
|
||||
out_packets.push_back(xc7series::ConfigurationPacket(
|
||||
1, xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FDRI, {}));
|
||||
out_packets.push_back(xc7series::ConfigurationPacket(
|
||||
2, xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FDRI, packet_data));
|
||||
|
||||
#if 0
|
||||
for (auto& packet : out_packets) {
|
||||
std::cout << packet << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write bitstream.
|
||||
xc7series::BitstreamWriter out_bitstream_writer(out_packets);
|
||||
std::ofstream out_file(FLAGS_output_file);
|
||||
if (!out_file) {
|
||||
std::cerr << "Unable to open file for writting: "
|
||||
<< FLAGS_output_file << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (uint32_t word : out_bitstream_writer) {
|
||||
out_file.put((word >> 24) & 0xFF);
|
||||
out_file.put((word >> 16) & 0xFF);
|
||||
out_file.put((word >> 8) & 0xFF);
|
||||
out_file.put((word)&0xFF);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue