| /* |
| * Copyright (C) 2017-2020 The Project X-Ray Authors. |
| * |
| * Use of this source code is governed by a ISC-style |
| * license that can be found in the LICENSE file or at |
| * https://opensource.org/licenses/ISC |
| * |
| * SPDX-License-Identifier: ISC |
| */ |
| #include <iostream> |
| |
| #include <prjxray/bit_ops.h> |
| #include <prjxray/xilinx/architectures.h> |
| #include <prjxray/xilinx/bitstream_writer.h> |
| |
| namespace prjxray { |
| namespace xilinx { |
| |
| template <> |
| // Per UG380 pg 78: Bus Width Auto Detection |
| typename BitstreamWriter<Spartan6>::header_t BitstreamWriter<Spartan6>::header_{ |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566}; |
| |
| // Per UG470 pg 80: Bus Width Auto Detection |
| template <> |
| typename BitstreamWriter<Series7>::header_t BitstreamWriter<Series7>::header_{ |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000000BB, 0x11220044, |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566}; |
| |
| template <> |
| typename BitstreamWriter<UltraScale>::header_t |
| BitstreamWriter<UltraScale>::header_{0xFFFFFFFF, 0x000000BB, 0x11220044, |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566}; |
| |
| template <> |
| typename BitstreamWriter<UltraScalePlus>::header_t |
| BitstreamWriter<UltraScalePlus>::header_{ |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000000BB, 0x11220044, |
| 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566}; |
| |
| uint32_t packet2header( |
| const ConfigurationPacket<Spartan6ConfigurationRegister>& packet) { |
| uint32_t ret = 0; |
| |
| ret = bit_field_set(ret, 15, 13, packet.header_type()); |
| |
| switch (packet.header_type()) { |
| case NONE: |
| // Bitstreams are 0 padded sometimes, essentially making |
| // a type 0 frame Ignore the other fields for now |
| break; |
| case TYPE1: { |
| // Table 5-20: Type 1 Packet Header Format |
| ret = bit_field_set(ret, 12, 11, packet.opcode()); |
| ret = bit_field_set(ret, 10, 5, packet.address()); |
| ret = bit_field_set(ret, 4, 0, packet.data().length()); |
| break; |
| } |
| case TYPE2: { |
| // Table 5-22: Type 2 Packet Header |
| ret = bit_field_set(ret, 12, 11, packet.opcode()); |
| ret = bit_field_set(ret, 10, 5, packet.address()); |
| break; |
| } |
| default: |
| break; |
| } |
| |
| return ret; |
| } |
| |
| uint32_t packet2header( |
| const ConfigurationPacket<Series7ConfigurationRegister>& packet) { |
| uint32_t ret = 0; |
| |
| ret = bit_field_set(ret, 31, 29, packet.header_type()); |
| |
| switch (packet.header_type()) { |
| case NONE: |
| // Bitstreams are 0 padded sometimes, essentially making |
| // a type 0 frame Ignore the other fields for now |
| break; |
| case TYPE1: { |
| // Table 5-20: Type 1 Packet Header Format |
| ret = bit_field_set(ret, 28, 27, packet.opcode()); |
| ret = bit_field_set(ret, 26, 13, packet.address()); |
| ret = bit_field_set(ret, 10, 0, packet.data().length()); |
| break; |
| } |
| case TYPE2: { |
| // Table 5-22: Type 2 Packet Header |
| // Note address is from previous type 1 header |
| ret = bit_field_set(ret, 28, 27, packet.opcode()); |
| ret = bit_field_set(ret, 26, 0, packet.data().length()); |
| break; |
| } |
| default: |
| break; |
| } |
| |
| return ret; |
| } |
| |
| } // namespace xilinx |
| } // namespace prjxray |