Skip to content

Commit

Permalink
Add support for gowin .fs files (input only)
Browse files Browse the repository at this point in the history
Add support for gowin .fs files (input only) . Includes implementation, documentation and regression test.
  • Loading branch information
danselmi committed Apr 11, 2023
1 parent 70dc28c commit 3d3123e
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The SRecord package understands a number of file formats:
* **Fairchild Fairbug**: input/output
* **Formatted Binary**: input/output
* **Four Packed Code (FPC)**: input/output
* **Gowin fs**: input;
* **Hexdump**: output only; a simple hexdump
* **HP64000 Absolute**: input only
* **IDT/sim**: input/output
Expand Down
1 change: 1 addition & 0 deletions doc/dictionaries/names.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Giancristofaro
Gracic
GraphViz
groff
Gowin
Hanspeter
Heilig
hexdump
Expand Down
56 changes: 56 additions & 0 deletions doc/man5/srec_gowin.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'\" t
.\" srecord - manipulate eprom load files
.\" Copyright (C) 2023 Daniel Anselmi
.\"
.\" 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 3 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, see
.\" <http://www.gnu.org/licenses/>.
.\"
.ds n) srec_gowin
.TH \*(n) 5 SRecord "Reference Manual"
.SH NAME
srec_gowin \- Gowin bitstream file format
.if require_index \{
.XX "srec_gowin(5)" "Gowin bitstream file format"
.\}
.SH DESCRIPTION
This format is the Gowin bitstream file format. It is generated by the IDE from Gowin to program their FPGAs.

Lines starting with "//" contain comments.
Each byte is represented by a string containing 8 chars of '0' or '1' for each byte.
A line can contain multiple bytes.
There is no spacing between multiple bytes except an optional newline.
Each line contains a multiple of 8 bits (except comment lines).

There is no addressing and no checksum in this format.

.SH EXAMPLE
Here is an example Gowin bitstream file.
It contains the data \[lq]Hello, World\[rq].
.RS
.nf
.ft CW
//comment
01001000
0110010101101100
01101100
0110111100101100
00100000
010101110110111101110010
0110110001100100
.ft P
.fi
.RE

.ds n) srec_cat
.so man1/z_copyright.so
1 change: 1 addition & 0 deletions srecord/arglex/tool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ srecord::arglex_tool::arglex_tool(int argc, char **argv) :
{ "-GENerate", token_generator },
{ "-GENerator", token_generator },
{ "-Gnu_CRypt", token_gcrypt }, // undocumented
{ "-GOwin_fs", token_gowin_fs },
{ "-GUess", token_guess, },
{ "-HAVal", token_haval, },
{ "-HEXadecimal_Dump", token_hexdump, },
Expand Down
1 change: 1 addition & 0 deletions srecord/arglex/tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class arglex_tool:
token_four_packed_code,
token_gcrypt,
token_generator,
token_gowin_fs,
token_guess,
token_haval,
token_hexdump,
Expand Down
6 changes: 6 additions & 0 deletions srecord/arglex/tool/input.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <srecord/input/file/formatted_binary.h>
#include <srecord/input/file/four_packed_code.h>
#include <srecord/input/file/efinix_bit.h>
#include <srecord/input/file/gowin_fs.h>
#include <srecord/input/file/hexdump.h>
#include <srecord/input/file/hp64k.h>
#include <srecord/input/file/idt.h>
Expand Down Expand Up @@ -347,6 +348,11 @@ srecord::arglex_tool::get_simple_input()
ifp = input_file_four_packed_code::create(fn);
break;

case token_gowin_fs:
token_next();
ifp = input_file_gowin_fs::create(fn);
break;

case token_guess:
token_next();
ifp = input_file::guess(fn, *this);
Expand Down
128 changes: 128 additions & 0 deletions srecord/input/file/gowin_fs.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// srecord - manipulate eprom load files
// Copyright (C) 2023 Daniel Anselmi
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 3 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 Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
#include <cctype>

#include <srecord/arglex/tool.h>
#include <srecord/input/file/gowin_fs.h>
#include <srecord/record.h>


srecord::input_file_gowin_fs::input_file_gowin_fs(
const std::string &a_filename
) :
input_file(a_filename),
address(0),
done(false)
{
}

srecord::input_file::pointer
srecord::input_file_gowin_fs::create(const std::string &a_filename)
{
return pointer(new input_file_gowin_fs(a_filename));
}

// See base class for documentation.
bool srecord::input_file_gowin_fs::read(record &record)
{
if (done)
return false;

int length = 0;
srecord::record::data_t data[srecord::record::max_data_length];

for (;;)
{
int c = peek_char();
if (c == EOF)
{
done = true;
break;
}
else if (c == '/')
{
skip_until_eol();
continue;
}
else if (c == '\n' || c == ' ' || c == '\t')
{
// Files from Gowin IDE don't have spaces or tabs between the
// data or lines with only spaces. We accept them here anyway.
get_char();
continue;
}

/* reading 8 chars to get a byte */
srecord::record::data_t d = get_byte_binary();
data[length++] = d;

if (length >= (int)sizeof(data))
break;
}

record = srecord::record(srecord::record::type_data, address, data, length);
address += length;
return true;
}

void
srecord::input_file_gowin_fs::skip_until_eol()
{
while (get_char() != '\n');
}

int
srecord::input_file_gowin_fs::get_byte_binary()
{
int val = 0;
for (int i = 0x80; i; i >>= 1)
{
int c = get_binary_digit_value();
if (c < 0)
fatal_error("expecting binary digit");
if (c)
val |= i;
}
return val;
}

int
srecord::input_file_gowin_fs::get_binary_digit_value()
{
int c = get_char();
if (c != '0' && c != '1')
return -1;
return c - '0';
}

const char *
srecord::input_file_gowin_fs::get_file_format_name()
const
{
return "Gowin bitstream";
}


int
srecord::input_file_gowin_fs::format_option_number()
const
{
return arglex_tool::token_gowin_fs;
}
120 changes: 120 additions & 0 deletions srecord/input/file/gowin_fs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//
// srecord - manipulate eprom load files
// Copyright (C) 2023 Daniel Anselmi
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 3 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 Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

#ifndef SRECORD_INPUT_GOWIN_FS_H
#define SRECORD_INPUT_GOWIN_FS_H

#include <srecord/input/file.h>

namespace srecord {

/**
* The srecord::input_file_gowin_fs class is used to represent the parse
* state when reading a gowin .fs file.
*/
class input_file_gowin_fs:
public input_file
{
public:
/**
* The destructor.
*/
virtual ~input_file_gowin_fs() = default;

/**
* The create class method is used to create new dynamically
* allocated instances of this class.
*
* @param file_name
* The name of the file to be read.
* @returns
* smart pointer to new instance
*/
static pointer create(const std::string &file_name);

/**
* The default constructor.
*/
input_file_gowin_fs() = delete;

/**
* The copy constructor.
*/
input_file_gowin_fs(const input_file_gowin_fs &) = delete;

/**
* The assignment operator. Do not use.
*/
input_file_gowin_fs &operator=(const input_file_gowin_fs &) = delete;

protected:
// See base class for documentation.
bool read(record &record);

// See base class for documentation.
const char *get_file_format_name() const;

// See base class for documentation.
int format_option_number() const;

private:
/**
* The constructor.
*
* @param file_name
* The name of the file to be read.
*/
input_file_gowin_fs(const std::string &file_name);

/**
* The address instance variable is used to remember the current
* address of the next data record. This is set and advanced by
* the #read method.
*/
uint32_t address;

/**
* The done instance variable is used to remember that we
* don't expect more input data.
*/
bool done;

/**
* The get_byte_binary method is used to fetch a byte value from
* the input. It calls get_binary_digit_value 8 times, and
* assembles them big-endian (most significant bit first).
*/
int get_byte_binary();

/**
* The get_binary_digit_value method is used to fetch one binary digit
* from the input, via the get_char method. It returns a value from 0 to 1.
* If there's currently not a binary digit in the input stream
* it returns -1.
*/
int get_binary_digit_value();

/**
* skip input until there is a newline in the input.
*/
void skip_until_eol();
};

};

#endif // SRECORD_INPUT_GOWIN_FS_H
Loading

0 comments on commit 3d3123e

Please sign in to comment.