Skip to content

Commit

Permalink
Initial skeleton of gpkjson
Browse files Browse the repository at this point in the history
azonenberg committed Jul 10, 2017
1 parent cabe653 commit 847a62d
Showing 6 changed files with 583 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_subdirectory(vendor)
add_subdirectory(gpdevboard)
add_subdirectory(greenpak4)
add_subdirectory(gpkjson)
add_subdirectory(gp4prog)
add_subdirectory(gp4par)
add_subdirectory(gp4tchar)
9 changes: 9 additions & 0 deletions src/gpkjson/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
add_executable(gpkjson
main.cpp
)

target_link_libraries(gpkjson
greenpak4 xbpar log)

install(TARGETS gpkjson
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
33 changes: 33 additions & 0 deletions src/gpkjson/gpkjson.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/***********************************************************************************************************************
* Copyright (C) 2016-2017 Andrew Zonenberg and contributors *
* *
* 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 2.1 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, you may *
* find one here: *
* https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt *
* or you may search the http://www.gnu.org website for the version 2.1 license, or you may write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
**********************************************************************************************************************/

#ifndef gpkjson_h
#define gpkjson_h

#include <cstdio>
#include <string>
#include <map>
#include <log.h>
#include <xbpar.h>
#include <Greenpak4.h>

//Console help
void ShowUsage();
void ShowVersion();

#endif
301 changes: 301 additions & 0 deletions src/gpkjson/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
/***********************************************************************************************************************
* Copyright (C) 2016-2017 Andrew Zonenberg and contributors *
* *
* 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 2.1 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, you may *
* find one here: *
* https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt *
* or you may search the http://www.gnu.org website for the version 2.1 license, or you may write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
**********************************************************************************************************************/

#include "gpkjson.h"

using namespace std;

int main(int argc, char* argv[])
{
Severity console_verbosity = Severity::NOTICE;

//Netlist file
string fname = "";

//Output file
string ofname = "";

//Disables colored output
bool noColors = false;

//Target chip
Greenpak4Device::GREENPAK4_PART part = Greenpak4Device::GREENPAK4_SLG46620;

//Parse command-line arguments
for(int i=1; i<argc; i++)
{
string s(argv[i]);

//Let the logger eat its args first
if(ParseLoggerArguments(i, argc, argv, console_verbosity))
continue;

else if(s == "--help")
{
ShowUsage();
return 0;
}
else if(s == "--version")
{
ShowVersion();
return 0;
}
else if( (s == "--part") || (s == "-p") )
{
if(i+1 < argc)
{
int p;
sscanf(argv[++i], "SLG%d", &p);

switch(p)
{
case 46620:
part = Greenpak4Device::GREENPAK4_SLG46620;
break;

case 46621:
part = Greenpak4Device::GREENPAK4_SLG46621;
break;

case 46140:
part = Greenpak4Device::GREENPAK4_SLG46140;
break;

default:
printf("ERROR: Invalid part (supported: SLG46620, SLG46621, SLG46140)\n");
return 1;
}
}
else
{
printf("ERROR: --part requires an argument\n");
return 1;
}
}
else if(s == "--nocolors")
noColors = true;
else if(s == "-o" || s == "--output")
{
if(i+1 < argc)
ofname = argv[++i];
else
{
printf("ERROR: --output requires an argument\n");
return 1;
}
}

//assume it's the netlist file if it's the first non-switch argument
else if( (s[0] != '-') && (fname == "") )
fname = s;

else
{
printf("ERROR: Unrecognized command-line argument \"%s\", use --help\n", s.c_str());
return 1;
}
}

//Netlist filenames must be specified
if( (fname == "") || (ofname == "") )
{
ShowUsage();
return 1;
}

//Set up logging
if(noColors)
g_log_sinks.emplace(g_log_sinks.begin(), new STDLogSink(console_verbosity));
else
g_log_sinks.emplace(g_log_sinks.begin(), new ColoredSTDLogSink(console_verbosity));

//Print header
if(console_verbosity >= Severity::NOTICE)
ShowVersion();

//Initialize the device
Greenpak4Device device(part);
if(!device.ReadFromFile(fname))
return 1;

/*
//Parse the unplaced netlist
//We need to load the netlist first to handle the unused_* attributes
LogNotice("\nLoading Yosys JSON file \"%s\".\n", fname.c_str());
Greenpak4Netlist netlist(fname, pcfname);
if(!netlist.Validate())
return 1;
//Print configuration
LogNotice("\nDevice configuration:\n");
{
LogIndenter li;
string dev = "<invalid>";
switch(part)
{
case Greenpak4Device::GREENPAK4_SLG46620:
dev = "SLG46620V";
break;
case Greenpak4Device::GREENPAK4_SLG46621:
dev = "SLG46621V";
break;
case Greenpak4Device::GREENPAK4_SLG46140:
dev = "SLG46140V";
break;
}
LogNotice("Target device: %s\n", dev.c_str());
LogNotice("VCC range: not yet implemented\n");
string pull;
string drive;
switch(unused_pull)
{
case Greenpak4IOB::PULL_NONE:
pull = "float";
break;
case Greenpak4IOB::PULL_DOWN:
pull = "pull down with ";
break;
case Greenpak4IOB::PULL_UP:
pull = "pull up with ";
break;
default:
LogError("Invalid pull direction\n");
return 1;
}
if(unused_pull != Greenpak4IOB::PULL_NONE)
{
switch(unused_drive)
{
case Greenpak4IOB::PULL_10K:
drive = "10K";
break;
case Greenpak4IOB::PULL_100K:
drive = "100K";
break;
case Greenpak4IOB::PULL_1M:
drive = "1M";
break;
default:
LogError("Invalid pull strength\n");
return 1;
}
}
LogNotice("Unused pins: %s%s\n", pull.c_str(), drive.c_str());
LogNotice("User ID code: %02x\n", userid);
LogNotice("Read protection: %s\n", readProtect ? "enabled" : "disabled");
LogNotice("I/O precharge: %s\n", ioPrecharge ? "enabled" : "disabled");
LogNotice("Charge pump: %s\n", disableChargePump ? "off" : "auto");
LogNotice("LDO: %s\n", ldoBypass ? "bypassed" : "enabled");
LogNotice("Boot retry: %d times\n", bootRetry);
}
//Create the device and initialize all IO pins
Greenpak4Device device(part, unused_pull, unused_drive);
device.SetIOPrecharge(ioPrecharge);
device.SetDisableChargePump(disableChargePump);
device.SetLDOBypass(ldoBypass);
device.SetNVMRetryCount(bootRetry);
//Attempt to load the timing data file, if present
//FIXME: get this from a sane location and make it chip specific
string tfname = "../../../timing.json";
LogNotice("\nLoading timing data file \"%s\"\n", tfname.c_str());
if(!device.LoadTimingData(tfname))
LogWarning("Timing data file not found, unable to do timing-driven placement or evaluate post-PAR timing\n");
//Do the actual P&R
LogNotice("\nImplementing top-level module \"%s\".\n", netlist.GetTopModule()->GetName().c_str());
if(!DoPAR(&netlist, &device))
return 1;
//Write the final bitstream
LogNotice("\nWriting final bitstream to output file \"%s\", using ID code 0x%x.\n",
ofname.c_str(), (int)userid);
{
LogIndenter li;
if(!device.WriteToFile(ofname, userid, readProtect))
return 1;
}
*/
return 0;
}

void ShowUsage()
{
/*
printf(// v 80th column
"Usage: gp4par [options] -p part -o bitstream.txt netlist.json\n"
" -c, --constraints <file>\n"
" Reads placement constraints from <file>\n"
" --debug\n"
" Prints lots of internal debugging information.\n"
" --disable-charge-pump\n"
" Disables the on-die charge pump which powers the analog hard IP when the\n"
" supply voltage drops below 2.7V. Provided for completeness since the\n"
" Silego GUI lets you specify it; there's no obvious reason to use it.\n"
" --io-precharge\n"
" Hooks a 2K resistor in parallel with pullup/down resistors during POR.\n"
" This can help external capacitive loads to reach a stable voltage faster.\n"
" -l, --logfile <file>\n"
" Causes verbose log messages to be written to <file>.\n"
" -L, --logfile-lines <file>\n"
" Causes verbose log messages to be written to <file>, flushing after\n"
" each line.\n"
" --ldo-bypass\n"
" Disable the on-die LDO and use an external 1.8V Vdd as Vcore.\n"
" May cause device damage if set with higher Vdd supply.\n"
" -o, --output <bitstream>\n"
" Writes bitstream into the specified file.\n"
" -p, --part\n"
" Specifies the part to target (SLG46620V, SLG46621V, or SLG46140V)\n"
" -q, --quiet\n"
" Causes only warnings and errors to be written to the console.\n"
" Specify twice to also silence warnings.\n"
" --unused-pull [down|up|float]\n"
" Specifies direction to pull unused pins.\n"
" --unused-drive [10k|100k|1m]\n"
" Specifies strength of pullup/down resistor on unused pins.\n"
" --verbose\n"
" Prints additional information about the design.\n");
*/
}

void ShowVersion()
{
printf(
"GreenPAK JSON netlist exporter by Andrew D. Zonenberg.\n"
"\n"
"License: LGPL v2.1+\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n");
}
235 changes: 235 additions & 0 deletions src/greenpak4/Greenpak4Device.cpp
Original file line number Diff line number Diff line change
@@ -984,6 +984,241 @@ string Greenpak4Device::GetPartAsString()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// File I/O

/**
@brief Reads the bitstream from a file
*/
bool Greenpak4Device::ReadFromFile(string fname)
{
//Allocate the bitstream
bool* bitstream = new bool[m_bitlen];
for(unsigned int i=0; i<m_bitlen; i++)
bitstream[i] = false;

//Open the file
FILE* fp = fopen(fname.c_str(), "r");
if(!fp)
{
LogError("Couldn't open %s for reading\n", fname.c_str());
return false;
}

//Parse the bitfile
char unused[128];
fgets(unused, sizeof(unused), fp);
int index;
int value;
unsigned int nlines = 0;
while(true)
{
if(2 != fscanf(fp, "%d %d //\n", &index, &value))
break;
if( ((size_t)index >= m_bitlen) || (index < 0) )
{
LogWarning("Ignoring invalid index %d (valid = 0...%d)\n", index, m_bitlen);
continue;
}
bitstream[index] = value;
nlines ++;
}
fclose(fp);

if(nlines != m_bitlen)
LogWarning("Bitstream may be incomplete (read %u lines, expected %u)\n", nlines, m_bitlen);

//Parse the bitstream
bool ok = true;

//Get the config data from each of our blocks
for(auto x : m_bitstuff)
{
if(!x->Load(bitstream))
{
LogError("Bitstream node %s failed to load\n", x->GetDescription().c_str());
ok = false;
}
}

/*
//Write chip-wide tuning data and ID code
switch(m_part)
{
case GREENPAK4_SLG46621:
//Tie the unused on-die IOB for pin 14 to ground
//TODO: warn if anything tried to use pin 14?
for(int i=1378; i<=1389; i++)
bitstream[i] = false;
//Fall through to 46620 for shared config.
//Other than the bondout for this IOB the devices are identical.
case GREENPAK4_SLG46620:
//FIXME: Disable ADC block (until we have the logic for that implemented)
bitstream[486] = true;
bitstream[487] = true;
bitstream[488] = true;
bitstream[489] = true;
bitstream[490] = true;
bitstream[491] = true;
//Force ADC block speed to 100 kHz (all other speeds not supported according to GreenPAK Designer)
//TODO: Do this in the ADC class once that exists
bitstream[838] = 0;
bitstream[839] = 1;
//Vref fine tune, magic value from datasheet (TODO do calibration?)
//Seems to have been removed from most recent datasheet
bitstream[891] = false;
bitstream[890] = false;
bitstream[889] = false;
bitstream[888] = false;
bitstream[887] = false;
//I/O precharge
bitstream[940] = m_ioPrecharge;
//Device ID; immutable on the device but added to aid verification
//5A: more data to follow
bitstream[1016] = false;
bitstream[1017] = true;
bitstream[1018] = false;
bitstream[1019] = true;
bitstream[1020] = true;
bitstream[1021] = false;
bitstream[1022] = true;
bitstream[1023] = false;
if(m_nvmLoadRetryCount != 1)
LogWarning("NVM retry count values other than 1 are not currently supported for SLG4662x\n");
//Internal LDO disable
bitstream[2008] = m_ldoBypass;
//Charge pump disable
bitstream[2010] = m_disableChargePump;
//User ID of the bitstream
bitstream[2031] = (userid & 0x01) ? true : false;
bitstream[2032] = (userid & 0x02) ? true : false;
bitstream[2033] = (userid & 0x04) ? true : false;
bitstream[2034] = (userid & 0x08) ? true : false;
bitstream[2035] = (userid & 0x10) ? true : false;
bitstream[2036] = (userid & 0x20) ? true : false;
bitstream[2037] = (userid & 0x40) ? true : false;
bitstream[2038] = (userid & 0x80) ? true : false;
//Read protection flag
bitstream[2039] = readProtect;
//A5: end of bitstream
bitstream[2040] = true;
bitstream[2041] = false;
bitstream[2042] = true;
bitstream[2043] = false;
bitstream[2044] = false;
bitstream[2045] = true;
bitstream[2046] = false;
bitstream[2047] = true;
break;
case GREENPAK4_SLG46140:
//FIXME: Disable ADC block (until we have the logic for that implemented)
bitstream[378] = true;
bitstream[379] = true;
bitstream[380] = true;
bitstream[381] = true;
bitstream[383] = true;
bitstream[383] = true;
//Force ADC block speed to 100 kHz (all other speeds not supported according to GreenPAK Designer)
//Note that the SLG46140V datasheet r100 still lists the other speed values, but SLG46620 rev 100 does not.
//Furthermore, GreenPAK Designer v6.02 complains about bitstreams generated using 2'b11.
//It says "setting speed to 100 kHz" and writes to 2'b10 instead. One of these is wrong, need to ask Silego.
//TODO: Do this in the ADC class once that exists
bitstream[542] = 1;
bitstream[543] = 1;
//Vref fine tune, magic value from datasheet (TODO do calibration?)
//Seems to have been removed from most recent datasheet, used rev 079 for this
bitstream[495] = false;
bitstream[494] = false;
bitstream[493] = false;
bitstream[492] = false;
bitstream[491] = false;
//I/O precharge
bitstream[760] = m_ioPrecharge;
//NVM boot retry
switch(m_nvmLoadRetryCount)
{
case 1:
bitstream[995] = false;
bitstream[994] = false;
break;
case 2:
bitstream[995] = false;
bitstream[994] = true;
break;
case 3:
bitstream[995] = true;
bitstream[994] = false;
break;
case 4:
bitstream[995] = true;
bitstream[994] = true;
break;
default:
LogError("NVM retry count for SLG46140 must be 1...4\n");
ok = false;
}
//Internal LDO disable
bitstream[1003] = m_ldoBypass;
//Charge pump disable
bitstream[1005] = m_disableChargePump;
//User ID of the bitstream
bitstream[1007] = (userid & 0x01) ? true : false;
bitstream[1008] = (userid & 0x02) ? true : false;
bitstream[1009] = (userid & 0x04) ? true : false;
bitstream[1010] = (userid & 0x08) ? true : false;
bitstream[1011] = (userid & 0x10) ? true : false;
bitstream[1012] = (userid & 0x20) ? true : false;
bitstream[1013] = (userid & 0x40) ? true : false;
bitstream[1014] = (userid & 0x80) ? true : false;
//Device ID; immutable on the device but added to aid verification
//A5: end of bitstream
bitstream[1016] = true;
bitstream[1017] = false;
bitstream[1018] = true;
bitstream[1019] = false;
bitstream[1020] = false;
bitstream[1021] = true;
bitstream[1022] = false;
bitstream[1023] = true;
break;
//Invalid device
default:
LogError("Greenpak4Device: WriteToFile(): unknown device\n");
ok = false;
}
*/
delete[] bitstream;
return ok;
}

/**
@brief Writes the bitstream to a file
5 changes: 4 additions & 1 deletion src/greenpak4/Greenpak4Device.h
Original file line number Diff line number Diff line change
@@ -44,7 +44,10 @@ class Greenpak4Device

virtual ~Greenpak4Device();

//Write to a bitfile
//Initialize this device from a bitfile
bool ReadFromFile(std::string fname);

//Write our config to a bitfile
bool WriteToFile(std::string fname, uint8_t userid, bool readProtect);

//Write to an in-memory array

0 comments on commit 847a62d

Please sign in to comment.