pld: add support for cologne chip gatemate fpgas 65/7565/10
authorDaniel Anselmi <danselmi@gmx.ch>
Fri, 24 Feb 2023 14:57:30 +0000 (15:57 +0100)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sun, 30 Apr 2023 14:55:14 +0000 (14:55 +0000)
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>
doc/openocd.texi
src/pld/Makefile.am
src/pld/gatemate.c [new file with mode: 0644]
src/pld/pld.c
tcl/board/gatemate_eval.cfg [new file with mode: 0644]
tcl/fpga/gatemate.cfg [new file with mode: 0644]

index cea02bd5429dcc17dea5b61d03fb861be8c6a545..f32ef347565ae1e2e92669d4602ad26930f2a83f 100644 (file)
@@ -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
index 22ae9fd208e6b5329ca2c354184b1b3a232d9415..69e457c96a11e91ad14cb75e07a9c0387199e7be 100644 (file)
@@ -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 (file)
index 0000000..afd27ef
--- /dev/null
@@ -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,
+};
index d9e01f16cd15a0867118fabd897a20961a22e284..dd8f8263fe7de0d94a75137bb82692af74e26649 100644 (file)
@@ -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 (file)
index 0000000..cc078a0
--- /dev/null
@@ -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 (file)
index 0000000..cc19fd4
--- /dev/null
@@ -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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)