New Programmable Logic Devices (PLD) subsystem by Michael Walle
git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1852 b68d4a1b-bc3d-0410-92ed-d4ac073336b7master
parent
4763d8162a
commit
183d46a331
@ -0,0 +1,34 @@
|
||||
With the Programmable Logic Devices (PLD) subsystem you can load a bitstream
|
||||
into a FPGA via JTAG. Besides benefits in development it supports production
|
||||
of boards with NOR flashes connected to the FPGA. You can load a fjmem core
|
||||
into the FPGA and program (fast!) the flash through it.
|
||||
|
||||
The subsystem needs several instructions to be defined. These have to be
|
||||
manually added by the user (eg. through the ~/.jtag/rc):
|
||||
|
||||
Spartan-3/Spartan-6:
|
||||
instruction CFG_OUT 000100 BYPASS
|
||||
instruction CFG_IN 000101 BYPASS
|
||||
instruction JSTART 001100 BYPASS
|
||||
instruction JPROGRAM 001011 BYPASS
|
||||
|
||||
Virtex-4:
|
||||
instruction CFG_OUT 1111000100 BYPASS
|
||||
instruction CFG_IN 1111000101 BYPASS
|
||||
instruction JPROGRAM 1111001011 BYPASS
|
||||
instruction JSTART 1111001100 BYPASS
|
||||
|
||||
|
||||
The following example flashes a NOR flash connected to the FGPA:
|
||||
|
||||
cable Turtelizer2 vid=0x0403 pid=0x6010
|
||||
detect
|
||||
instruction CFG_OUT 000100 BYPASS
|
||||
instruction CFG_IN 000101 BYPASS
|
||||
instruction JSTART 001100 BYPASS
|
||||
instruction JPROGRAM 001011 BYPASS
|
||||
pld load /path/to/fjmem.bit
|
||||
initbus fjmem opcode=000010
|
||||
detectflash 0
|
||||
flashmem 0 /path/to/data.bin
|
||||
pld reconfigure
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Support for Programmable Logic Devices (PLD)
|
||||
*
|
||||
* Copyright (C) 2010, Michael Walle
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by Michael Walle <michael@walle.cc>, 2010
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef URJ_PLD_H
|
||||
#define URJ_PLD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
urj_chain_t *chain;
|
||||
urj_part_t *part;
|
||||
void *priv;
|
||||
} urj_pld_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
int (*detect) (urj_pld_t *pld);
|
||||
int (*print_status) (urj_pld_t *pld);
|
||||
int (*configure) (urj_pld_t *pld, FILE *pld_file);
|
||||
int (*reconfigure) (urj_pld_t *pld);
|
||||
int (*read_register) (urj_pld_t *pld, uint32_t reg, uint32_t *value);
|
||||
int (*write_register) (urj_pld_t *pld, uint32_t reg, uint32_t value);
|
||||
int register_width;
|
||||
} urj_pld_driver_t;
|
||||
|
||||
/**
|
||||
* urj_pld_configure(chain, pld_file)
|
||||
*
|
||||
* Main entry point for the 'pld load' command.
|
||||
*
|
||||
* XXX Description here
|
||||
*
|
||||
* @param chain pointer to global chain
|
||||
* @param pld_file file handle of PLD file
|
||||
*
|
||||
* @return
|
||||
* URJ_STATUS_OK, URJ_STATUS_FAIL
|
||||
*/
|
||||
int urj_pld_configure (urj_chain_t *chain, FILE *pld_file);
|
||||
|
||||
/**
|
||||
* urj_pld_reconfigure(chain)
|
||||
*
|
||||
* Main entry point for the 'pld reconfigure' command.
|
||||
*
|
||||
* XXX Description here
|
||||
*
|
||||
* @param chain pointer to global chain
|
||||
*
|
||||
* @return
|
||||
* URJ_STATUS_OK, URJ_STATUS_FAIL
|
||||
*/
|
||||
int urj_pld_reconfigure (urj_chain_t *chain);
|
||||
|
||||
/**
|
||||
* urj_pld_status(chain)
|
||||
*
|
||||
* Main entry point for the 'pld status' command.
|
||||
*
|
||||
* XXX Description here
|
||||
*
|
||||
* @param chain pointer to global chain
|
||||
*
|
||||
* @return
|
||||
* URJ_STATUS_OK, URJ_STATUS_FAIL
|
||||
*/
|
||||
int urj_pld_print_status (urj_chain_t *chain);
|
||||
|
||||
/**
|
||||
* urj_pld_read_register(chain)
|
||||
*
|
||||
* Main entry point for the 'pld readreg' command.
|
||||
*
|
||||
* XXX Description here
|
||||
*
|
||||
* @param chain pointer to global chain
|
||||
* @param reg register number
|
||||
*
|
||||
* @return
|
||||
* URJ_STATUS_OK, URJ_STATUS_FAIL
|
||||
*/
|
||||
int urj_pld_read_register (urj_chain_t *chain, uint32_t reg);
|
||||
|
||||
/**
|
||||
* urj_pld_write_register(chain)
|
||||
*
|
||||
* Main entry point for the 'pld writereg' command.
|
||||
*
|
||||
* XXX Description here
|
||||
*
|
||||
* @param chain pointer to global chain
|
||||
* @param reg register number
|
||||
* @param value value
|
||||
*
|
||||
* @return
|
||||
* URJ_STATUS_OK, URJ_STATUS_FAIL
|
||||
*/
|
||||
int urj_pld_write_register (urj_chain_t *chain, uint32_t reg, uint32_t value);
|
||||
|
||||
#endif /* URJ_PLD_H */
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Support for Programmable Logic Devices (PLD)
|
||||
*
|
||||
* Copyright (C) 2010, Michael Walle
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by Michael Walle <michael@walle.cc>, 2010
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <urjtag/error.h>
|
||||
#include <urjtag/log.h>
|
||||
|
||||
#include <urjtag/pld.h>
|
||||
#include <urjtag/cmd.h>
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
static int
|
||||
cmd_pld_run (urj_chain_t *chain, char *params[])
|
||||
{
|
||||
FILE *pld_file;
|
||||
int num_params;
|
||||
int result = URJ_STATUS_OK;
|
||||
|
||||
num_params = urj_cmd_params (params);
|
||||
if (num_params < 2)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_SYNTAX,
|
||||
_("%s: #parameters should be >= %d, not %d"),
|
||||
params[0], 2, urj_cmd_params (params));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (strcasecmp (params[1], "load") == 0)
|
||||
{
|
||||
if (num_params < 3)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_SYNTAX,
|
||||
_("%s: no filename specified"),
|
||||
params[0]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if ((pld_file = fopen (params[2], "rb")) != NULL)
|
||||
{
|
||||
result = urj_pld_configure (chain, pld_file);
|
||||
fclose (pld_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
urj_error_IO_set (_("%s: cannot open file '%s'"),
|
||||
params[0], params[1]);
|
||||
result = URJ_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp (params[1], "status") == 0)
|
||||
{
|
||||
result = urj_pld_print_status (chain);
|
||||
}
|
||||
else if (strcasecmp (params[1], "readreg") == 0)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
if (num_params < 3)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_SYNTAX,
|
||||
_("%s: #parameters should be >= %d, not %d"),
|
||||
params[0], 3, urj_cmd_params (params));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (urj_cmd_get_number (params[2], ®) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
result = urj_pld_read_register (chain, reg);
|
||||
}
|
||||
else if (strcasecmp (params[1], "writereg") == 0)
|
||||
{
|
||||
unsigned long reg;
|
||||
unsigned long value;
|
||||
|
||||
if (num_params < 4)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_SYNTAX,
|
||||
_("%s: #parameters should be >= %d, not %d"),
|
||||
params[0], 4, urj_cmd_params (params));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (urj_cmd_get_number (params[2], ®) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (urj_cmd_get_number (params[3], &value) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
result = urj_pld_write_register (chain, reg, value);
|
||||
}
|
||||
else if (strcasecmp (params[1], "reconfigure") == 0)
|
||||
{
|
||||
result = urj_pld_reconfigure (chain);
|
||||
}
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_SYNTAX,
|
||||
_("%s: unkown command"), params[0]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_pld_help (void)
|
||||
{
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL,
|
||||
_("Usage: %s load PLDFILE\n"
|
||||
"Usage: %s reconfigure\n"
|
||||
"Usage: %s status\n"
|
||||
"Usage: %s readreg REG\n"
|
||||
"Usage: %s writereg REG VALUE\n"
|
||||
"Configure FPGA from PLDFILE, query status, read and write registers.\n"),
|
||||
"pld", "pld", "pld", "pld", "pld");
|
||||
}
|
||||
|
||||
const urj_cmd_t urj_cmd_pld = {
|
||||
"pld",
|
||||
N_("configure a Programmable Logic Device from file"),
|
||||
cmd_pld_help,
|
||||
cmd_pld_run
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Copyright (C) 2010 Michael Walle
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# Written by Michael Walle <michael@walle.cc>, 2010.
|
||||
#
|
||||
|
||||
include $(top_srcdir)/Makefile.rules
|
||||
|
||||
noinst_LTLIBRARIES = libpld.la
|
||||
|
||||
libpld_la_SOURCES = \
|
||||
pld.c \
|
||||
xilinx_bitstream.c \
|
||||
xilinx.c
|
||||
|
||||
AM_CFLAGS = $(WARNINGCFLAGS)
|
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Support for Programmable Logic Devices (PLD)
|
||||
*
|
||||
* Copyright (C) 2010, Michael Walle
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by Michael Walle <michael@walle.cc>, 2010
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <urjtag/pld.h>
|
||||
#include <urjtag/chain.h>
|
||||
#include <urjtag/part.h>
|
||||
#include <urjtag/tap_register.h>
|
||||
#include "xilinx.h"
|
||||
|
||||
const urj_pld_driver_t * const urj_pld_drivers[] = {
|
||||
&urj_pld_xc3s_driver,
|
||||
&urj_pld_xc6s_driver,
|
||||
&urj_pld_xc4v_driver,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const urj_pld_driver_t *pld_driver = NULL;
|
||||
static urj_pld_t pld;
|
||||
|
||||
static int
|
||||
set_pld_driver (urj_chain_t *chain, urj_part_t *part)
|
||||
{
|
||||
int i;
|
||||
uint32_t idcode;
|
||||
|
||||
pld_driver = NULL;
|
||||
pld.chain = chain;
|
||||
pld.part = part;
|
||||
|
||||
for (i = 0; urj_pld_drivers[i] != NULL; i++)
|
||||
{
|
||||
if (urj_pld_drivers[i]->detect (&pld) == URJ_STATUS_OK)
|
||||
{
|
||||
pld_driver = urj_pld_drivers[i];
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
idcode = urj_tap_register_get_value (part->id);
|
||||
urj_log (URJ_LOG_LEVEL_ERROR,
|
||||
_("No PLD driver for device with ID %08x\n"),
|
||||
idcode);
|
||||
|
||||
urj_error_set (URJ_ERROR_UNSUPPORTED, _("PLD not supported"));
|
||||
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
int
|
||||
urj_pld_configure (urj_chain_t *chain, FILE *pld_file)
|
||||
{
|
||||
urj_part_t *part;
|
||||
|
||||
part = urj_tap_chain_active_part (chain);
|
||||
|
||||
if (part == NULL)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (set_pld_driver (chain, part) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (pld_driver->configure == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_UNSUPPORTED,
|
||||
_("PLD doesn't support this operation"));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return pld_driver->configure (&pld, pld_file);
|
||||
}
|
||||
|
||||
int
|
||||
urj_pld_reconfigure (urj_chain_t *chain)
|
||||
{
|
||||
urj_part_t *part;
|
||||
|
||||
part = urj_tap_chain_active_part (chain);
|
||||
|
||||
if (part == NULL)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (set_pld_driver (chain, part) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (pld_driver->reconfigure == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_UNSUPPORTED,
|
||||
_("PLD doesn't support this operation"));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return pld_driver->reconfigure (&pld);
|
||||
}
|
||||
|
||||
int
|
||||
urj_pld_print_status (urj_chain_t *chain)
|
||||
{
|
||||
urj_part_t *part;
|
||||
|
||||
part = urj_tap_chain_active_part (chain);
|
||||
|
||||
if (part == NULL)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (set_pld_driver (chain, part) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (pld_driver->print_status == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_UNSUPPORTED,
|
||||
_("PLD doesn't support this operation"));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return pld_driver->print_status (&pld);
|
||||
}
|
||||
|
||||
int
|
||||
urj_pld_read_register (urj_chain_t *chain, uint32_t reg)
|
||||
{
|
||||
urj_part_t *part;
|
||||
uint32_t value;
|
||||
|
||||
part = urj_tap_chain_active_part (chain);
|
||||
|
||||
if (part == NULL)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (set_pld_driver (chain, part) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (pld_driver->read_register == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_UNSUPPORTED,
|
||||
_("PLD doesn't support this operation"));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (pld_driver->read_register (&pld, reg, &value) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, N_("REG[%d]=0x%0*x\n"),
|
||||
reg, pld_driver->register_width * 2, value);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
urj_pld_write_register (urj_chain_t *chain, uint32_t reg, uint32_t data)
|
||||
{
|
||||
urj_part_t *part;
|
||||
|
||||
part = urj_tap_chain_active_part (chain);
|
||||
|
||||
if (part == NULL)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (set_pld_driver (chain, part) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (pld_driver->write_register == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_UNSUPPORTED,
|
||||
_("PLD doesn't support this operation"));
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return pld_driver->write_register (&pld, reg, data);
|
||||
}
|
@ -0,0 +1,784 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Driver for Xilinx FPGAs
|
||||
*
|
||||
* Copyright (C) 2010, Michael Walle
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by Michael Walle <michael@walle.cc>, 2010
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <urjtag/tap.h>
|
||||
#include <urjtag/part.h>
|
||||
#include <urjtag/chain.h>
|
||||
#include <urjtag/tap_state.h>
|
||||
#include <urjtag/tap_register.h>
|
||||
#include <urjtag/data_register.h>
|
||||
#include <urjtag/part_instruction.h>
|
||||
#include <urjtag/pld.h>
|
||||
#include <urjtag/bitops.h>
|
||||
#include "xilinx.h"
|
||||
|
||||
static int
|
||||
xlx_set_ir_and_shift (urj_chain_t *chain, urj_part_t *part, char *iname)
|
||||
{
|
||||
urj_part_set_instruction (part, iname);
|
||||
if (part->active_instruction == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_PLD, "unknown instruction '%s'", iname);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
urj_tap_chain_shift_instructions (chain);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_set_dr_and_shift (urj_chain_t *chain, urj_part_t *part,
|
||||
uint64_t value, int exitmode)
|
||||
{
|
||||
if (part->active_instruction == NULL)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_register_t *r = part->active_instruction->data_register->in;
|
||||
urj_tap_register_set_value (r, value);
|
||||
urj_tap_defer_shift_register (chain, r, NULL, exitmode);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_instruction_resize_dr (urj_part_t *part, const char *ir_name,
|
||||
const char *dr_name, int dr_len)
|
||||
{
|
||||
urj_data_register_t *d;
|
||||
urj_part_instruction_t *i;
|
||||
|
||||
i = urj_part_find_instruction (part, ir_name);
|
||||
|
||||
if (i == NULL)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_PLD, "unknown instruction '%s'", ir_name);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
d = urj_part_find_data_register (part, dr_name);
|
||||
|
||||
if (d == NULL)
|
||||
{
|
||||
d = urj_part_data_register_alloc (dr_name, dr_len);
|
||||
d->next = part->data_registers;
|
||||
part->data_registers = d;
|
||||
}
|
||||
else if (d->in->len != dr_len)
|
||||
{
|
||||
/* data register length does not match */
|
||||
urj_part_data_register_realloc (d, dr_len);
|
||||
}
|
||||
|
||||
i->data_register = d;
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_write_register_xc3s (urj_pld_t *pld, uint32_t reg, uint32_t value)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
|
||||
if (value & 0xffff0000)
|
||||
{
|
||||
urj_log (URJ_LOG_LEVEL_WARNING,
|
||||
_("Only 16 bit values supported. Truncating value."));
|
||||
|
||||
value &= 0xffff;
|
||||
}
|
||||
|
||||
/* use the same data register as they have the same length */
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
if (xlx_instruction_resize_dr (part, "CFG_OUT", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_capture_dr (chain);
|
||||
/* sync */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xffff),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xaa99),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* type 2 packet (word count = 1) */
|
||||
reg = 0x3001 | ((reg & 0x3f) << 5);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (reg),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (value),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
|
||||
urj_tap_chain_flush (chain);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_write_register_xc4v (urj_pld_t *pld, uint32_t reg, uint32_t value)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
|
||||
/* use the same data register as they have the same length */
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", 32)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
if (xlx_instruction_resize_dr (part, "CFG_OUT", "CFG_DR", 32)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_capture_dr (chain);
|
||||
/* sync */
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0xffffffff),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0xaa995566),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0x20000000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* type 2 packet (word count = 1) */
|
||||
reg = 0x30000001 | ((reg & 0x1f) << 13);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (reg),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (value),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0x20000000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0x20000000),
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
|
||||
urj_tap_chain_flush (chain);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_write_register_xc6s (urj_pld_t *pld, uint32_t reg, uint32_t value)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
|
||||
if (value & 0xffff0000)
|
||||
{
|
||||
urj_log (URJ_LOG_LEVEL_WARNING,
|
||||
_("Only 16 bit values supported. Truncating value."));
|
||||
|
||||
value &= 0xffff;
|
||||
}
|
||||
|
||||
/* use the same data register as they have the same length */
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
if (xlx_instruction_resize_dr (part, "CFG_OUT", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_capture_dr (chain);
|
||||
/* sync */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xaa99),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x5566),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* type 2 packet (word count = 1) */
|
||||
reg = 0x3001 | ((reg & 0x3f) << 5);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (reg),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (value),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
|
||||
urj_tap_chain_flush (chain);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_read_register_xc3s (urj_pld_t *pld, uint32_t reg, uint32_t *value)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
urj_tap_register_t *r;
|
||||
|
||||
/* use the same data register as they have the same length */
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
if (xlx_instruction_resize_dr (part, "CFG_OUT", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_capture_dr (chain);
|
||||
/* sync */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xffff),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xaa99),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* type 1 packet (word count = 1) */
|
||||
reg = 0x2801 | ((reg & 0x3f) << 5);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (reg),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_OUT") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_chain_shift_data_registers (chain, 1);
|
||||
|
||||
r = part->active_instruction->data_register->out;
|
||||
|
||||
*value = flip16 (urj_tap_register_get_value (r));
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_read_register_xc4v (urj_pld_t *pld, uint32_t reg, uint32_t *value)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
urj_tap_register_t *r;
|
||||
|
||||
/* use the same data register as they have the same length */
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", 32)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
if (xlx_instruction_resize_dr (part, "CFG_OUT", "CFG_DR", 32)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_capture_dr (chain);
|
||||
/* sync */
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0xffffffff),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0xaa995566),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0x20000000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* type 1 packet (word count = 1) */
|
||||
reg = 0x28000001 | ((reg & 0x1f) << 13);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (reg),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0x20000000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip32 (0x20000000),
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_OUT") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_chain_shift_data_registers (chain, 1);
|
||||
|
||||
r = part->active_instruction->data_register->out;
|
||||
|
||||
*value = flip32 (urj_tap_register_get_value (r));
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_read_register_xc6s (urj_pld_t *pld, uint32_t reg, uint32_t *value)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
urj_tap_register_t *r;
|
||||
|
||||
/* use the same data register as they have the same length */
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
if (xlx_instruction_resize_dr (part, "CFG_OUT", "CFG_DR", 16)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_capture_dr (chain);
|
||||
/* sync */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xffff),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0xaa99),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x5566),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* type 1 packet (word count = 1) */
|
||||
reg = 0x2801 | ((reg & 0x3f) << 5);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (reg),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
/* noop */
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_SHIFT);
|
||||
xlx_set_dr_and_shift (chain, part, flip16 (0x2000),
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_OUT") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_chain_shift_data_registers (chain, 1);
|
||||
|
||||
r = part->active_instruction->data_register->out;
|
||||
|
||||
*value = flip16 (urj_tap_register_get_value (r));
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_print_status_xc3s (urj_pld_t *pld)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
if (xlx_read_register_xc3s (pld, XILINX_XC3S_REG_STAT, &status)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("Status register (0x%04x)\n"), status);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tSYNC_TIMEOUT %d\n"),
|
||||
(status & XC3S_STATUS_SYNC_TIMEOUT) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tSEUR_ERR %d\n"),
|
||||
(status & XC3S_STATUS_SEU_ERR) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDONE %d\n"),
|
||||
(status & XC3S_STATUS_DONE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tINIT %d\n"),
|
||||
(status & XC3S_STATUS_INIT) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tMODE_M2 %d\n"),
|
||||
(status & XC3S_STATUS_MODE_M2) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tMODE_M1 %d\n"),
|
||||
(status & XC3S_STATUS_MODE_M1) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tMODE_M0 %d\n"),
|
||||
(status & XC3S_STATUS_MODE_M0) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tVSEL_VS2 %d\n"),
|
||||
(status & XC3S_STATUS_VSEL_VS2) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tVSEL_VS1 %d\n"),
|
||||
(status & XC3S_STATUS_VSEL_VS1) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tVSEL_VS0 %d\n"),
|
||||
(status & XC3S_STATUS_VSEL_VS0) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tGHIGH_B %d\n"),
|
||||
(status & XC3S_STATUS_GHIGH_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tGWE %d\n"),
|
||||
(status & XC3S_STATUS_GWE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tGTS_CFG_B %d\n"),
|
||||
(status & XC3S_STATUS_GTS_CFG_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDCM_LOCK %d\n"),
|
||||
(status & XC3S_STATUS_DCM_LOCK) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tID_ERROR %d\n"),
|
||||
(status & XC3S_STATUS_ID_ERROR) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tCRC_ERROR %d\n"),
|
||||
(status & XC3S_STATUS_CRC_ERROR) ? 1 : 0);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_print_status_xc4v (urj_pld_t *pld)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
if (xlx_read_register_xc4v (pld, XILINX_XC4V_REG_STAT, &status)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("Status register (0x%08x)\n"), status);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_DEC_ERROR %d\n"),
|
||||
(status & XC4V_STATUS_DEC_ERROR) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_ID_ERROR %d\n"),
|
||||
(status & XC4V_STATUS_ID_ERROR) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_DONE %d\n"),
|
||||
(status & XC4V_STATUS_DONE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_RELEASE_DONE %d\n"),
|
||||
(status & XC4V_STATUS_RELEASE_DONE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_INIT %d\n"),
|
||||
(status & XC4V_STATUS_INIT) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_INIT_COMPLETE %d\n"),
|
||||
(status & XC4V_STATUS_INIT_COMPLETE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_MODE_M2 %d\n"),
|
||||
(status & XC4V_STATUS_MODE_M2) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_MODE_M1 %d\n"),
|
||||
(status & XC4V_STATUS_MODE_M1) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_MODE_M0 %d\n"),
|
||||
(status & XC4V_STATUS_MODE_M0) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_GHIGH_B %d\n"),
|
||||
(status & XC4V_STATUS_GHIGH_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_GWE %d\n"),
|
||||
(status & XC4V_STATUS_GWE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_GTS_CFG_B %d\n"),
|
||||
(status & XC4V_STATUS_GTS_CFG_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_EOS %d\n"),
|
||||
(status & XC4V_STATUS_EOS) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_DCI_MATCH %d\n"),
|
||||
(status & XC4V_STATUS_DCI_MATCH) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_DCM_LOCK %d\n"),
|
||||
(status & XC4V_STATUS_DCM_LOCK) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_PART_SECURED %d\n"),
|
||||
(status & XC4V_STATUS_PART_SECURED) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tXC4V_STATUS_CRC_ERROR %d\n"),
|
||||
(status & XC4V_STATUS_CRC_ERROR) ? 1 : 0);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
xlx_print_status_xc6s (urj_pld_t *pld)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
if (xlx_read_register_xc6s (pld, XILINX_XC6S_REG_STAT, &status)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("Status register (0x%04x)\n"), status);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tSWWD %d\n"),
|
||||
(status & XC6S_STATUS_SWWD) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tIN_PWRDN %d\n"),
|
||||
(status & XC6S_STATUS_IN_PWRDN) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDONE %d\n"),
|
||||
(status & XC6S_STATUS_DONE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tINIT_B %d\n"),
|
||||
(status & XC6S_STATUS_INIT_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tMODE_M1 %d\n"),
|
||||
(status & XC6S_STATUS_MODE_M1) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tMODE_M0 %d\n"),
|
||||
(status & XC6S_STATUS_MODE_M0) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tHSWAPEN %d\n"),
|
||||
(status & XC6S_STATUS_HSWAPEN) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tPART_SECURED %d\n"),
|
||||
(status & XC6S_STATUS_PART_SECURED) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDEC_ERROR %d\n"),
|
||||
(status & XC6S_STATUS_DEC_ERROR) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tGHIGH_B %d\n"),
|
||||
(status & XC6S_STATUS_GHIGH_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tGWE %d\n"),
|
||||
(status & XC6S_STATUS_GWE) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tGTS_CFG_B %d\n"),
|
||||
(status & XC6S_STATUS_GTS_CFG_B) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDCM_LOCK %d\n"),
|
||||
(status & XC6S_STATUS_DCM_LOCK) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tID_ERROR %d\n"),
|
||||
(status & XC6S_STATUS_ID_ERROR) ? 1 : 0);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tCRC_ERROR %d\n"),
|
||||
(status & XC6S_STATUS_CRC_ERROR) ? 1 : 0);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_configure (urj_pld_t *pld, FILE *bit_file)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
urj_part_instruction_t *i;
|
||||
xlx_bitstream_t *bs;
|
||||
uint32_t u;
|
||||
int dr_len;
|
||||
char *dr_data;
|
||||
int status = URJ_STATUS_OK;
|
||||
|
||||
/* set all devices in bypass mode */
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
bs = xlx_bitstream_alloc ();
|
||||
if (bs == NULL)
|
||||
{
|
||||
status = URJ_STATUS_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* parse bit file */
|
||||
if (xlx_bitstream_load_bit (bit_file, bs) != URJ_STATUS_OK)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_PLD, _("Invalid bitfile"));
|
||||
|
||||
status = URJ_STATUS_FAIL;
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("Bitstream information:\n"));
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDesign: %s\n"), bs->design);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tPart name: %s\n"), bs->part_name);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tDate: %s\n"), bs->date);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tTime: %s\n"), bs->time);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("\tBitstream length: %d\n"), bs->length);
|
||||
|
||||
dr_len = bs->length * 8;
|
||||
|
||||
if (xlx_instruction_resize_dr (part, "CFG_IN", "CFG_DR", dr_len)
|
||||
!= URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
i = urj_part_find_instruction (part, "CFG_IN");
|
||||
|
||||
/* copy data into shift register */
|
||||
dr_data = i->data_register->in->data;
|
||||
for (u = 0; u < bs->length; u++)
|
||||
{
|
||||
/* flip bits */
|
||||
dr_data[8*u+0] = (bs->data[u] & 0x80) ? 1 : 0;
|
||||
dr_data[8*u+1] = (bs->data[u] & 0x40) ? 1 : 0;
|
||||
dr_data[8*u+2] = (bs->data[u] & 0x20) ? 1 : 0;
|
||||
dr_data[8*u+3] = (bs->data[u] & 0x10) ? 1 : 0;
|
||||
dr_data[8*u+4] = (bs->data[u] & 0x08) ? 1 : 0;
|
||||
dr_data[8*u+5] = (bs->data[u] & 0x04) ? 1 : 0;
|
||||
dr_data[8*u+6] = (bs->data[u] & 0x02) ? 1 : 0;
|
||||
dr_data[8*u+7] = (bs->data[u] & 0x01) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "JPROGRAM") != URJ_STATUS_OK)
|
||||
{
|
||||
status = URJ_STATUS_FAIL;
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
{
|
||||
status = URJ_STATUS_FAIL;
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
/* wait until device is unconfigured */
|
||||
do {
|
||||
urj_tap_chain_shift_instructions_mode (chain, 1, 1,
|
||||
URJ_CHAIN_EXITMODE_IDLE);
|
||||
} while (!(urj_tap_register_get_value (part->active_instruction->out)
|
||||
& XILINX_SR_INIT));
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "CFG_IN") != URJ_STATUS_OK)
|
||||
{
|
||||
status = URJ_STATUS_FAIL;
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
urj_tap_chain_shift_data_registers (chain, 0);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "JSTART") != URJ_STATUS_OK)
|
||||
{
|
||||
status = URJ_STATUS_FAIL;
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
urj_tap_chain_defer_clock (chain, 0, 0, 32);
|
||||
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
urj_tap_chain_flush (chain);
|
||||
|
||||
fail_free:
|
||||
xlx_bitstream_free (bs);
|
||||
fail:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_reconfigure (urj_pld_t *pld)
|
||||
{
|
||||
urj_chain_t *chain = pld->chain;
|
||||
urj_part_t *part = pld->part;
|
||||
|
||||
urj_tap_reset_bypass (chain);
|
||||
|
||||
if (xlx_set_ir_and_shift (chain, part, "JPROGRAM") != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_tap_reset (chain);
|
||||
urj_tap_chain_flush (chain);
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_detect_xc3s (urj_pld_t *pld)
|
||||
{
|
||||
urj_part_t *part = pld->part;
|
||||
uint32_t idcode;
|
||||
uint32_t family;
|
||||
|
||||
/* get fpga family from idcode */
|
||||
idcode = urj_tap_register_get_value (part->id);
|
||||
family = (idcode >> 21) & 0x7f;
|
||||
|
||||
switch (family)
|
||||
{
|
||||
case XILINX_FAMILY_XC3S:
|
||||
case XILINX_FAMILY_XC3SE:
|
||||
case XILINX_FAMILY_XC3A:
|
||||
case XILINX_FAMILY_XC3AN:
|
||||
case XILINX_FAMILY_XC3SD:
|
||||
return URJ_STATUS_OK;
|
||||
default:
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_detect_xc4v (urj_pld_t *pld)
|
||||
{
|
||||
urj_part_t *part = pld->part;
|
||||
uint32_t idcode;
|
||||
uint32_t family;
|
||||
|
||||
/* get fpga family from idcode */
|
||||
idcode = urj_tap_register_get_value (part->id);
|
||||
family = (idcode >> 21) & 0x7f;
|
||||
|
||||
switch (family)
|
||||
{
|
||||
case XILINX_FAMILY_XC4VFX:
|
||||
case XILINX_FAMILY_XC4VLX:
|
||||
case XILINX_FAMILY_XC4VSX:
|
||||
return URJ_STATUS_OK;
|
||||
default:
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xlx_detect_xc6s (urj_pld_t *pld)
|
||||
{
|
||||
urj_part_t *part = pld->part;
|
||||
uint32_t idcode;
|
||||
uint32_t family;
|
||||
|
||||
/* get fpga family from idcode */
|
||||
idcode = urj_tap_register_get_value (part->id);
|
||||
family = (idcode >> 21) & 0x7f;
|
||||
|
||||
switch (family)
|
||||
{
|
||||
case XILINX_FAMILY_XC6S:
|
||||
return URJ_STATUS_OK;
|
||||
default:
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
const urj_pld_driver_t urj_pld_xc3s_driver = {
|
||||
.name = N_("Xilinx Spartan 3 Family"),
|
||||
.detect = xlx_detect_xc3s,
|
||||
.print_status = xlx_print_status_xc3s,
|
||||
.configure = xlx_configure,
|
||||
.reconfigure = xlx_reconfigure,
|
||||
.read_register = xlx_read_register_xc3s,
|
||||
.write_register = xlx_write_register_xc3s,
|
||||
.register_width = 2,
|
||||
};
|
||||
|
||||
const urj_pld_driver_t urj_pld_xc6s_driver = {
|
||||
.name = N_("Xilinx Spartan 6 Family"),
|
||||
.detect = xlx_detect_xc6s,
|
||||
.print_status = xlx_print_status_xc6s,
|
||||
.configure = xlx_configure,
|
||||
.reconfigure = xlx_reconfigure,
|
||||
.read_register = xlx_read_register_xc6s,
|
||||
.write_register = xlx_write_register_xc6s,
|
||||
.register_width = 2,
|
||||
};
|
||||
|
||||
const urj_pld_driver_t urj_pld_xc4v_driver = {
|
||||
.name = N_("Xilinx Virtex 4 Family"),
|
||||
.detect = xlx_detect_xc4v,
|
||||
.print_status = xlx_print_status_xc4v,
|
||||
.configure = xlx_configure,
|
||||
.reconfigure = xlx_reconfigure,
|
||||
.read_register = xlx_read_register_xc4v,
|
||||
.write_register = xlx_write_register_xc4v,
|
||||
.register_width = 2,
|
||||
};
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Driver for Xilinx FPGAs
|
||||
*
|
||||
* Copyright (C) 2010, Michael Walle
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by Michael Walle <michael@walle.cc>, 2010
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef URJ_PLD_XILINX_H
|
||||
#define URJ_PLD_XILINX_H
|
||||
|
||||
#include <urjtag/pld.h>
|
||||
|
||||
#define XILINX_SR_DONE URJ_BIT(5)
|
||||
#define XILINX_SR_INIT URJ_BIT(4)
|
||||
#define XILINX_SR_ISC_ENABLED URJ_BIT(3)
|
||||
#define XILINX_SR_ISC_DONE URJ_BIT(2)
|
||||
|
||||
#define XILINX_XC3S_REG_STAT 8
|
||||
#define XILINX_XC4V_REG_STAT 7
|
||||
#define XILINX_XC6S_REG_STAT 8
|
||||
|
||||
#define XILINX_FAMILY_XC2V 0x08
|
||||
#define XILINX_FAMILY_XC3S 0x0A
|
||||
#define XILINX_FAMILY_XC4VLX 0x0B
|
||||
#define XILINX_FAMILY_XC3SE 0x0E
|
||||
#define XILINX_FAMILY_XC4VFX 0x0F
|
||||
#define XILINX_FAMILY_XC4VSX 0x10
|
||||
#define XILINX_FAMILY_XC3A 0x11
|
||||
#define XILINX_FAMILY_XC3AN 0x13
|
||||
#define XILINX_FAMILY_XC3SD 0x1C
|
||||
#define XILINX_FAMILY_XC5VLX 0x14
|
||||
#define XILINX_FAMILY_XC5VLXT 0x15
|
||||
#define XILINX_FAMILY_XC5VSXT 0x17
|
||||
#define XILINX_FAMILY_XC5CFXT 0x19
|
||||
#define XILINX_FAMILY_XC5CTXT 0x22
|
||||
#define XILINX_FAMILY_XC6S 0x20
|
||||
|
||||
#define XC3S_STATUS_SYNC_TIMEOUT URJ_BIT(15)
|
||||
#define XC3S_STATUS_SEU_ERR URJ_BIT(14)
|
||||
#define XC3S_STATUS_DONE URJ_BIT(13)
|
||||
#define XC3S_STATUS_INIT URJ_BIT(12)
|
||||
#define XC3S_STATUS_MODE_M2 URJ_BIT(11)
|
||||
#define XC3S_STATUS_MODE_M1 URJ_BIT(10)
|
||||
#define XC3S_STATUS_MODE_M0 URJ_BIT(9)
|
||||
#define XC3S_STATUS_VSEL_VS2 URJ_BIT(8)
|
||||
#define XC3S_STATUS_VSEL_VS1 URJ_BIT(7)
|
||||
#define XC3S_STATUS_VSEL_VS0 URJ_BIT(6)
|
||||
#define XC3S_STATUS_GHIGH_B URJ_BIT(5)
|
||||
#define XC3S_STATUS_GWE URJ_BIT(4)
|
||||
#define XC3S_STATUS_GTS_CFG_B URJ_BIT(3)
|
||||
#define XC3S_STATUS_DCM_LOCK URJ_BIT(2)
|
||||
#define XC3S_STATUS_ID_ERROR URJ_BIT(1)
|
||||
#define XC3S_STATUS_CRC_ERROR URJ_BIT(0)
|
||||
|
||||
#define XC4V_STATUS_DEC_ERROR URJ_BIT(16)
|
||||
#define XC4V_STATUS_ID_ERROR URJ_BIT(15)
|
||||
#define XC4V_STATUS_DONE URJ_BIT(14)
|
||||
#define XC4V_STATUS_RELEASE_DONE URJ_BIT(13)
|
||||
#define XC4V_STATUS_INIT URJ_BIT(12)
|
||||
#define XC4V_STATUS_INIT_COMPLETE URJ_BIT(12)
|
||||
#define XC4V_STATUS_MODE_M2 URJ_BIT(10)
|
||||
#define XC4V_STATUS_MODE_M1 URJ_BIT(9)
|
||||
#define XC4V_STATUS_MODE_M0 URJ_BIT(8)
|
||||
#define XC4V_STATUS_GHIGH_B URJ_BIT(7)
|
||||
#define XC4V_STATUS_GWE URJ_BIT(6)
|
||||
#define XC4V_STATUS_GTS_CFG_B URJ_BIT(5)
|
||||
#define XC4V_STATUS_EOS URJ_BIT(4)
|
||||
#define XC4V_STATUS_DCI_MATCH URJ_BIT(3)
|
||||
#define XC4V_STATUS_DCM_LOCK URJ_BIT(2)
|
||||
#define XC4V_STATUS_PART_SECURED URJ_BIT(1)
|
||||
#define XC4V_STATUS_CRC_ERROR URJ_BIT(0)
|
||||
|
||||
#define XC6S_STATUS_SWWD URJ_BIT(15)
|
||||
#define XC6S_STATUS_IN_PWRDN URJ_BIT(14)
|
||||
#define XC6S_STATUS_DONE URJ_BIT(13)
|
||||
#define XC6S_STATUS_INIT_B URJ_BIT(12)
|
||||
#define XC6S_STATUS_MODE_M1 URJ_BIT(10)
|
||||
#define XC6S_STATUS_MODE_M0 URJ_BIT(9)
|
||||
#define XC6S_STATUS_HSWAPEN URJ_BIT(8)
|
||||
#define XC6S_STATUS_PART_SECURED URJ_BIT(7)
|
||||
#define XC6S_STATUS_DEC_ERROR URJ_BIT(6)
|
||||
#define XC6S_STATUS_GHIGH_B URJ_BIT(5)
|
||||
#define XC6S_STATUS_GWE URJ_BIT(4)
|
||||
#define XC6S_STATUS_GTS_CFG_B URJ_BIT(3)
|
||||
#define XC6S_STATUS_DCM_LOCK URJ_BIT(2)
|
||||
#define XC6S_STATUS_ID_ERROR URJ_BIT(1)
|
||||
#define XC6S_STATUS_CRC_ERROR URJ_BIT(0)
|
||||
|
||||
extern const urj_pld_driver_t urj_pld_xc3s_driver;
|
||||
extern const urj_pld_driver_t urj_pld_xc6s_driver;
|
||||
extern const urj_pld_driver_t urj_pld_xc4v_driver;
|
||||
|
||||
typedef struct {
|
||||
char *design;
|
||||
char *part_name;
|
||||
char *date;
|
||||
char *time;
|
||||
uint32_t length;
|
||||
uint8_t *data;
|
||||
} xlx_bitstream_t;
|
||||
|
||||
int xlx_bitstream_load_bit (FILE *BIT_FILE, xlx_bitstream_t *bs);
|
||||
xlx_bitstream_t* xlx_bitstream_alloc (void);
|
||||
void xlx_bitstream_free (xlx_bitstream_t *bs);
|
||||
|
||||
#endif /* URJ_PLD_XILINX_H */
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Functions to parse Xilinx bitstream files
|
||||
*
|
||||
* Copyright (C) 2010, Michael Walle
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by Michael Walle <michael@walle.cc>, 2010
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <urjtag/log.h>
|
||||
#include <urjtag/error.h>
|
||||
|
||||
#include "xilinx.h"
|
||||
|
||||
static int
|
||||
xlx_read_section (FILE *bit_file, char *id, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
int lenbytes;
|
||||
|
||||
/* first read 1 bytes, the section key */
|
||||
if (fread (buf, 1, 1, bit_file) != 1)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
*id = buf[0];
|
||||
|
||||
/* section 'e' has 4 bytes indicating section length */
|
||||
if (*id == 'e')
|
||||
lenbytes = 4;
|
||||
else
|
||||
lenbytes = 2;
|
||||
|
||||
/* first read 1 bytes */
|
||||
if (fread (buf, 1, lenbytes, bit_file) != lenbytes)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
/* second and third is section length */
|
||||
if (*id != 'e')
|
||||
*len = buf[0] << 8 | buf[1];
|
||||
else
|
||||
*len = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
|
||||
|
||||
/* now allocate memory for data */
|
||||
*data = malloc (*len);
|
||||
|
||||
if (fread (*data, 1, *len, bit_file) != *len)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
xlx_bitstream_load_bit (FILE *bit_file, xlx_bitstream_t *bs)
|
||||
{
|
||||
char sid = 0;
|
||||
uint8_t *sdata;
|
||||
uint32_t slen;
|
||||
|
||||
uint8_t buf[128];
|
||||
uint8_t header[] = {
|
||||
0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0,
|
||||
0x0f, 0xf0, 0x00, 0x00, 0x01,
|
||||
};
|
||||
|
||||
if (fread (buf, 1, sizeof (header), bit_file) != sizeof (header))
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (memcmp (buf, header, sizeof (header)) != 0)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_DEBUG,
|
||||
_("Valid xilinx bitfile header found.\n"));
|
||||
|
||||
while (sid != 'e')
|
||||
{
|
||||
if (xlx_read_section (bit_file, &sid, &sdata, &slen) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_DEBUG,
|
||||
_("Read section id=%c len=%d.\n"), sid, slen);
|
||||
|
||||
/* make sure that strings are terminated */
|
||||
if (sid != 'e')
|
||||
sdata[slen-1] = '\0';
|
||||
|
||||
switch (sid)
|
||||
{
|
||||
case 'a': bs->design = (char *) sdata; break;
|
||||
case 'b': bs->part_name = (char *) sdata; break;
|
||||
case 'c': bs->date = (char *) sdata; break;
|
||||
case 'd': bs->time = (char *) sdata; break;
|
||||
case 'e': bs->data = sdata; bs->length = slen; break;
|
||||
}
|
||||
}
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
xlx_bitstream_t *
|
||||
xlx_bitstream_alloc (void)
|
||||
{
|
||||
xlx_bitstream_t *bs = calloc (1, sizeof (xlx_bitstream_t));
|
||||
|
||||
if (!bs)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("malloc(%zu) fails"),
|
||||
sizeof (xlx_bitstream_t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
void
|
||||
xlx_bitstream_free (xlx_bitstream_t *bs)
|
||||
{
|
||||
free (bs->design);
|
||||
free (bs->part_name);
|
||||
free (bs->date);
|
||||
free (bs->time);
|
||||
free (bs->data);
|
||||
|
||||
free (bs);
|
||||
}
|
Loading…
Reference in New Issue