Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Martin Schmölzer 2013-01-08 09:53:40 +01:00
commit 94502c39a7
4 changed files with 219 additions and 40 deletions

107
README
View File

@ -17,6 +17,109 @@ compatible licence that is similar in terms to the MIT license
or the 2-clause BSD license).
Getting Started
===============
To build Yosys simply typoe 'make' in this directory. You need
a C++ compiler with C++11 support (up-to-date CLANG or GCC is
recommended) and some standard tools such as GNU Flex, GNU Bison,
and GNU Make. It might be neccessary to make some changes to
the config section of the Makefile.
$ vi Makefile
$ make
$ make test
$ sudo make install
Yosys can be used using the interactive command shell, using
synthesis scripts or using command line arguments. Let's perform
a simple synthesis job using the interactive command shell:
$ ./yosys
yosys>
reading the design using the verilog frontend:
yosys> read_verilog tests/simple/fiedler-cooley.v
writing the design to the console in yosys's internal format:
yosys> write_ilang
convert processes (always blocks) to netlist elements and perform
some simple optimizations:
yosys> proc; opt
display design netlist using 'gv' as postscript viewer:
yosys> show -viewer gv
translating netlist to gate logic and perform some simple optimizations:
yosys> techmap; opt
write design netlist to a new verilog file:
yosys> write_verilog synth.v
a simmilar synthesis can be performed using yosys command line options only:
$ ./yosys -o synth.v -p proc -p opt -p techmap -p opt tests/simple/fiedler-cooley.v
or using a simple synthesis script:
$ cat synth.ys
read_verilog tests/simple/fiedler-cooley.v
proc; opt; techmap; opt
write_verilog synth.v
$ ././yosys synth.ys
It is also possible to only have the synthesis commands but not the read/write
commands in the synthesis script:
$ cat synth.ys
proc; opt; techmap; opt
$ ./yosys -o synth.v tests/simple/fiedler-cooley.v synth.ys
The following synthesis script works reasonable for all designs:
# check design hierarchy
hierarchy
# translate processes (always blocks) and memories (arrays)
proc; memory; opt
# detect and optimize FSM encodings
fsm; opt
# convert to gate logic
techmap; opt
If ABC (http://www.eecs.berkeley.edu/~alanmi/abc/) is installed and
a cell library is given in the file liberty mycells.lib, the following
synthesis script will synthesize for the given cell library:
# the high-level stuff
hierarchy; proc; memory; opt; fsm; opt
# mapping to internal cell library
techmap
# mapping flip-flops to mycells.lib
dfflibmap -liberty mycells.lib
# mapping logic to mycells.lib
abc -liberty mycells.lib
# cleanup
opt
Yosys is under construction. A more detailed documentation will follow.
Unsupported Verilog-2005 Features
=================================
@ -83,7 +186,7 @@ TODOs / Open Bugs
- TCL and Python interfaces to frontends, passes, backends and RTLIL
- Additional internal cell types: $bitcount, $pla, $lut and $pmux
- Additional internal cell types: $pla and $lut
- Subsystem for selecting stuff (and limiting scope of passes)
@ -93,5 +196,5 @@ TODOs / Open Bugs
- Smarter resource sharing pass (add MUXes and get rid of duplicated cells)
- FSM state encoding and technology mapping
- Better FSM state encoding and technology mapping

View File

@ -140,6 +140,40 @@ static const char *create_prompt(RTLIL::Design *design)
return buffer;
}
static void shell(RTLIL::Design *design)
{
log_cmd_error_throw = true;
rl_readline_name = "yosys";
rl_attempted_completion_function = readline_completion;
char *command = NULL;
while ((command = readline(create_prompt(design))) != NULL)
{
if (command[strspn(command, " \t\r\n")] == 0)
continue;
add_history(command);
try {
assert(design->selection_stack.size() == 1);
Pass::call(design, command);
} catch (int) {
while (design->selection_stack.size() > 1)
design->selection_stack.pop_back();
log_reset_stack();
}
}
log_cmd_error_throw = false;
}
struct ShellPass : public Pass {
ShellPass() : Pass("shell") { }
virtual void execute(std::vector<std::string>, RTLIL::Design *design) {
shell(design);
}
} ShellPass;
int main(int argc, char **argv)
{
std::string frontend_command = "auto";
@ -149,6 +183,8 @@ int main(int argc, char **argv)
std::string scriptfile = "";
bool got_output_filename = false;
Pass::init_register();
RTLIL::Design *design = new RTLIL::Design;
design->selection_stack.push_back(RTLIL::Selection());
log_push();
@ -196,33 +232,10 @@ int main(int argc, char **argv)
if (log_errfile == NULL)
log_files.push_back(stderr);
if (optind == argc && passes_commands.size() == 0 && scriptfile.empty())
{
log_cmd_error_throw = true;
rl_readline_name = "yosys";
rl_attempted_completion_function = readline_completion;
char *command = NULL;
while ((command = readline(create_prompt(design))) != NULL)
{
if (command[strspn(command, " \t\r\n")] == 0)
continue;
add_history(command);
try {
assert(design->selection_stack.size() == 1);
Pass::call(design, command);
} catch (int) {
while (design->selection_stack.size() > 1)
design->selection_stack.pop_back();
log_reset_stack();
}
}
if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) {
if (!got_output_filename)
backend_command = "";
log_cmd_error_throw = false;
shell(design);
}
while (optind < argc)
@ -248,6 +261,8 @@ int main(int argc, char **argv)
log_errfile = NULL;
log_files.clear();
Pass::done_register();
return 0;
}

View File

@ -23,8 +23,14 @@
#include <string.h>
using namespace REGISTER_INTERN;
#define MAX_REG_COUNT 1000
namespace REGISTER_INTERN
{
int raw_register_count = 0;
bool raw_register_done = false;
Pass *raw_register_array[MAX_REG_COUNT];
namespace REGISTER_INTERN {
std::map<std::string, Frontend*> frontend_register;
std::map<std::string, Pass*> pass_register;
std::map<std::string, Backend*> backend_register;
@ -34,13 +40,36 @@ std::vector<std::string> Frontend::next_args;
Pass::Pass(std::string name) : pass_name(name)
{
assert(pass_register.count(name) == 0);
pass_register[name] = this;
assert(!raw_register_done);
assert(raw_register_count < MAX_REG_COUNT);
raw_register_array[raw_register_count++] = this;
}
void Pass::run_register()
{
assert(pass_register.count(pass_name) == 0);
pass_register[pass_name] = this;
}
void Pass::init_register()
{
if (raw_register_done)
done_register();
while (raw_register_count > 0)
raw_register_array[--raw_register_count]->run_register();
raw_register_done = true;
}
void Pass::done_register()
{
frontend_register.clear();
pass_register.clear();
backend_register.clear();
raw_register_done = false;
}
Pass::~Pass()
{
pass_register.erase(pass_name);
}
void Pass::help()
@ -92,9 +121,20 @@ void Pass::extra_args(std::vector<std::string> args, size_t argidx, RTLIL::Desig
void Pass::call(RTLIL::Design *design, std::string command)
{
std::vector<std::string> args;
char *s = strdup(command.c_str());
for (char *p = strtok(s, " \t\r\n"); p; p = strtok(NULL, " \t\r\n"))
args.push_back(p);
char *s = strdup(command.c_str()), *saveptr;
for (char *p = strtok_r(s, " \t\r\n", &saveptr); p; p = strtok_r(NULL, " \t\r\n", &saveptr)) {
std::string str = p;
int strsz = str.size();
if (strsz > 0 && str[strsz-1] == ';') {
while (strsz > 0 && str[strsz-1] == ';')
strsz--;
if (strsz > 0)
args.push_back(str.substr(0, strsz));
call(design, args);
args.clear();
} else
args.push_back(str);
}
free(s);
call(design, args);
}
@ -114,13 +154,19 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
Frontend::Frontend(std::string name) : Pass("read_"+name), frontend_name(name)
{
assert(frontend_register.count(name) == 0);
frontend_register[name] = this;
}
void Frontend::run_register()
{
assert(pass_register.count(pass_name) == 0);
pass_register[pass_name] = this;
assert(frontend_register.count(frontend_name) == 0);
frontend_register[frontend_name] = this;
}
Frontend::~Frontend()
{
frontend_register.erase(frontend_name);
}
void Frontend::execute(std::vector<std::string> args, RTLIL::Design *design)
@ -200,13 +246,19 @@ void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filenam
Backend::Backend(std::string name) : Pass("write_"+name), backend_name(name)
{
assert(backend_register.count(name) == 0);
backend_register[name] = this;
}
void Backend::run_register()
{
assert(pass_register.count(pass_name) == 0);
pass_register[pass_name] = this;
assert(backend_register.count(backend_name) == 0);
backend_register[backend_name] = this;
}
Backend::~Backend()
{
backend_register.erase(backend_name);
}
void Backend::execute(std::vector<std::string> args, RTLIL::Design *design)

View File

@ -30,6 +30,7 @@ struct Pass
{
std::string pass_name;
Pass(std::string name);
virtual void run_register();
virtual ~Pass();
virtual void help();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) = 0;
@ -40,12 +41,16 @@ struct Pass
static void call(RTLIL::Design *design, std::string command);
static void call(RTLIL::Design *design, std::vector<std::string> args);
static void init_register();
static void done_register();
};
struct Frontend : Pass
{
std::string frontend_name;
Frontend(std::string name);
virtual void run_register();
virtual ~Frontend();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design);
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
@ -61,6 +66,7 @@ struct Backend : Pass
{
std::string backend_name;
Backend(std::string name);
virtual void run_register();
virtual ~Backend();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design);
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
@ -72,6 +78,9 @@ struct Backend : Pass
};
namespace REGISTER_INTERN {
extern int raw_register_count;
extern bool raw_register_done;
extern Pass *raw_register_array[];
extern std::map<std::string, Pass*> pass_register;
extern std::map<std::string, Frontend*> frontend_register;
extern std::map<std::string, Backend*> backend_register;