aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Anselmi <danselmi@gmx.ch>2023-02-24 15:57:30 +0100
committerAntonio Borneo <borneo.antonio@gmail.com>2023-04-30 14:55:14 +0000
commit682f927f8e4e6c6216c6d0b259b3c24b9f3f6342 (patch)
tree16e2248a5ba094ed5e01a1d2cbcb35e8551bc472
parent4b56c73ef3781c3232056b57be6d0d2ae3486a4a (diff)
downloadriscv-openocd-682f927f8e4e6c6216c6d0b259b3c24b9f3f6342.zip
riscv-openocd-682f927f8e4e6c6216c6d0b259b3c24b9f3f6342.tar.gz
riscv-openocd-682f927f8e4e6c6216c6d0b259b3c24b9f3f6342.tar.bz2
pld: add support for cologne chip gatemate fpgas
Change-Id: I0bf5a52ee6a7f0287524619114eba0cfccf6ac81 Signed-off-by: Daniel Anselmi <danselmi@gmx.ch> Reviewed-on: https://review.openocd.org/c/openocd/+/7565 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
-rw-r--r--doc/openocd.texi6
-rw-r--r--src/pld/Makefile.am1
-rw-r--r--src/pld/gatemate.c241
-rw-r--r--src/pld/pld.c2
-rw-r--r--tcl/board/gatemate_eval.cfg16
-rw-r--r--tcl/fpga/gatemate.cfg16
6 files changed, 282 insertions, 0 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index cea02bd..f32ef34 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -8566,6 +8566,12 @@ The files @verb{|.fs|} and @verb{|.bin|} generated by Gowin FPGA Designer are su
@end deffn
+@deffn {FPGA Driver} {gatemate}
+This driver can be used to load the bitstream into GateMate FPGAs form CologneChip.
+The files @verb{|.bit|} and @verb{|.cfg|} both generated by p_r tool from CologneChip are supported.
+@end deffn
+
+
@node General Commands
@chapter General Commands
@cindex commands
diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am
index 22ae9fd..69e457c 100644
--- a/src/pld/Makefile.am
+++ b/src/pld/Makefile.am
@@ -6,6 +6,7 @@ noinst_LTLIBRARIES += %D%/libpld.la
%D%/ecp2_3.c \
%D%/ecp5.c \
%D%/efinix.c \
+ %D%/gatemate.c \
%D%/gowin.c \
%D%/intel.c \
%D%/lattice.c \
diff --git a/src/pld/gatemate.c b/src/pld/gatemate.c
new file mode 100644
index 0000000..afd27ef
--- /dev/null
+++ b/src/pld/gatemate.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Copyright (C) 2022 by Daniel Anselmi *
+ * danselmi@gmx.ch *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/jtag.h>
+#include <jtag/adapter.h>
+#include "pld.h"
+#include "raw_bit.h"
+
+#define JTAG_CONFIGURE 0x06
+
+struct gatemate_pld_device {
+ struct jtag_tap *tap;
+};
+
+struct gatemate_bit_file {
+ struct raw_bit_file raw_file;
+ size_t capacity;
+};
+
+static int gatemate_add_byte_to_bitfile(struct gatemate_bit_file *bit_file, uint8_t byte)
+{
+ const size_t chunk_size = 8192;
+ if (bit_file->raw_file.length + 1 > bit_file->capacity) {
+ uint8_t *buffer;
+ if (bit_file->raw_file.data)
+ buffer = realloc(bit_file->raw_file.data, bit_file->capacity + chunk_size);
+ else
+ buffer = malloc(chunk_size);
+ if (!buffer) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ bit_file->raw_file.data = buffer;
+ bit_file->capacity += chunk_size;
+ }
+
+ bit_file->raw_file.data[bit_file->raw_file.length++] = byte;
+
+ return ERROR_OK;
+}
+
+static int gatemate_read_cfg_line(struct gatemate_bit_file *bit_file, const char *line_buffer, size_t nread)
+{
+ for (size_t idx = 0; idx < nread; ++idx) {
+ if (line_buffer[idx] == ' ') {
+ continue;
+ } else if (line_buffer[idx] == 0) {
+ break;
+ } else if (idx + 1 < nread) {
+ if (isxdigit(line_buffer[idx]) && isxdigit(line_buffer[idx + 1])) {
+ uint8_t byte;
+ unhexify(&byte, line_buffer + idx, 2);
+ int retval = gatemate_add_byte_to_bitfile(bit_file, byte);
+ if (retval != ERROR_OK)
+ return retval;
+ } else if (line_buffer[idx] == '/' && line_buffer[idx + 1] == '/') {
+ break;
+ }
+ ++idx;
+ } else {
+ LOG_ERROR("parsing failed");
+ return ERROR_FAIL;
+ }
+ }
+ return ERROR_OK;
+}
+
+static int gatemate_getline(char **buffer, size_t *buf_size, FILE *input_file)
+{
+ const size_t chunk_size = 32;
+ if (!*buffer)
+ *buf_size = 0;
+
+ size_t read = 0;
+ do {
+ if (read + 1 > *buf_size) {
+ char *new_buffer;
+ if (*buffer)
+ new_buffer = realloc(*buffer, *buf_size + chunk_size);
+ else
+ new_buffer = malloc(chunk_size);
+ if (!new_buffer) {
+ LOG_ERROR("Out of memory");
+ return -1;
+ }
+ *buffer = new_buffer;
+ *buf_size += chunk_size;
+ }
+
+ int c = fgetc(input_file);
+ if ((c == EOF && read) || (char)c == '\n') {
+ (*buffer)[read++] = 0;
+ return read;
+ } else if (c == EOF) {
+ return -1;
+ }
+
+ (*buffer)[read++] = (char)c;
+ } while (1);
+
+ return -1;
+}
+
+static int gatemate_read_cfg_file(struct gatemate_bit_file *bit_file, const char *filename)
+{
+ FILE *input_file = fopen(filename, "r");
+
+ if (!input_file) {
+ LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
+ return ERROR_PLD_FILE_LOAD_FAILED;
+ }
+
+ int retval = ERROR_OK;
+ char *line_buffer = NULL;
+ size_t buffer_length = 0;
+ int nread;
+ while (((nread = gatemate_getline(&line_buffer, &buffer_length, input_file)) != -1) && (retval == ERROR_OK))
+ retval = gatemate_read_cfg_line(bit_file, line_buffer, (size_t)nread);
+
+ if (line_buffer)
+ free(line_buffer);
+
+ fclose(input_file);
+ if (retval != ERROR_OK)
+ free(bit_file->raw_file.data);
+ return retval;
+}
+
+static int gatemate_read_file(struct gatemate_bit_file *bit_file, const char *filename)
+{
+ memset(bit_file, 0, sizeof(struct gatemate_bit_file));
+
+ if (!filename || !bit_file)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* check if binary .bit or ascii .cfg */
+ const char *file_suffix_pos = strrchr(filename, '.');
+ if (!file_suffix_pos) {
+ LOG_ERROR("Unable to detect filename suffix");
+ return ERROR_PLD_FILE_LOAD_FAILED;
+ }
+
+ if (strcasecmp(file_suffix_pos, ".bit") == 0)
+ return cpld_read_raw_bit_file(&bit_file->raw_file, filename);
+ else if (strcasecmp(file_suffix_pos, ".cfg") == 0)
+ return gatemate_read_cfg_file(bit_file, filename);
+
+ LOG_ERROR("Filetype not supported, expecting .bit or .cfg file");
+ return ERROR_PLD_FILE_LOAD_FAILED;
+}
+
+static int gatemate_set_instr(struct jtag_tap *tap, uint8_t new_instr)
+{
+ struct scan_field field;
+ field.num_bits = tap->ir_length;
+ void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
+ if (!t) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ field.out_value = t;
+ buf_set_u32(t, 0, field.num_bits, new_instr);
+ field.in_value = NULL;
+ jtag_add_ir_scan(tap, &field, TAP_IDLE);
+ jtag_add_runtest(3, TAP_IDLE);
+ free(t);
+ return ERROR_OK;
+}
+
+static int gatemate_load(struct pld_device *pld_device, const char *filename)
+{
+ if (!pld_device)
+ return ERROR_FAIL;
+
+ struct gatemate_pld_device *gatemate_info = pld_device->driver_priv;
+
+ if (!gatemate_info || !gatemate_info->tap)
+ return ERROR_FAIL;
+ struct jtag_tap *tap = gatemate_info->tap;
+
+ struct gatemate_bit_file bit_file;
+ int retval = gatemate_read_file(&bit_file, filename);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = gatemate_set_instr(tap, JTAG_CONFIGURE);
+ if (retval != ERROR_OK)
+ return retval;
+
+ struct scan_field field;
+ field.num_bits = bit_file.raw_file.length * 8;
+ field.out_value = bit_file.raw_file.data;
+ field.in_value = NULL;
+ jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+
+ retval = jtag_execute_queue();
+ free(bit_file.raw_file.data);
+
+ return retval;
+}
+
+PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
+{
+ struct jtag_tap *tap;
+
+ struct gatemate_pld_device *gatemate_info;
+
+ if (CMD_ARGC != 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ tap = jtag_tap_by_string(CMD_ARGV[1]);
+ if (!tap) {
+ command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
+ return ERROR_FAIL;
+ }
+
+ gatemate_info = malloc(sizeof(struct gatemate_pld_device));
+ if (!gatemate_info) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ gatemate_info->tap = tap;
+
+ pld->driver_priv = gatemate_info;
+
+ return ERROR_OK;
+}
+
+struct pld_driver gatemate_pld = {
+ .name = "gatemate",
+ .pld_device_command = &gatemate_pld_device_command,
+ .load = &gatemate_load,
+};
diff --git a/src/pld/pld.c b/src/pld/pld.c
index d9e01f1..dd8f826 100644
--- a/src/pld/pld.c
+++ b/src/pld/pld.c
@@ -19,6 +19,7 @@
/* pld drivers
*/
extern struct pld_driver efinix_pld;
+extern struct pld_driver gatemate_pld;
extern struct pld_driver gowin_pld;
extern struct pld_driver intel_pld;
extern struct pld_driver lattice_pld;
@@ -26,6 +27,7 @@ extern struct pld_driver virtex2_pld;
static struct pld_driver *pld_drivers[] = {
&efinix_pld,
+ &gatemate_pld,
&gowin_pld,
&intel_pld,
&lattice_pld,
diff --git a/tcl/board/gatemate_eval.cfg b/tcl/board/gatemate_eval.cfg
new file mode 100644
index 0000000..cc078a0
--- /dev/null
+++ b/tcl/board/gatemate_eval.cfg
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# GateMateTM FPGA Evaluation Board
+# https://www.colognechip.com/programmable-logic/gatemate-evaluation-board/
+#
+
+adapter driver ftdi
+ftdi vid_pid 0x0403 0x6010
+
+ftdi channel 0
+ftdi layout_init 0x0014 0x011b
+reset_config none
+transport select jtag
+adapter speed 6000
+
+source [find fpga/gatemate.cfg]
diff --git a/tcl/fpga/gatemate.cfg b/tcl/fpga/gatemate.cfg
new file mode 100644
index 0000000..cc19fd4
--- /dev/null
+++ b/tcl/fpga/gatemate.cfg
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# GateMateTM FPGA
+# https://www.colognechip.com/programmable-logic/gatemate/
+# https://colognechip.com/docs/ds1001-gatemate1-datasheet-latest.pdf
+
+if { [info exists CHIPNAME] } {
+ set _CHIPNAME $CHIPNAME
+} else {
+ set _CHIPNAME gatemate
+}
+
+jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \
+ -expected-id 0x20000001
+
+pld device gatemate $_CHIPNAME.tap