diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/calc.cc | 30 | ||||
-rw-r--r-- | kernel/celltypes.h | 14 | ||||
-rw-r--r-- | kernel/driver.cc | 30 | ||||
-rw-r--r-- | kernel/fstdata.cc | 28 | ||||
-rw-r--r-- | kernel/log.cc | 3 | ||||
-rw-r--r-- | kernel/log.h | 17 | ||||
-rw-r--r-- | kernel/mem.cc | 1 | ||||
-rw-r--r-- | kernel/register.cc | 109 | ||||
-rw-r--r-- | kernel/rtlil.h | 2 | ||||
-rw-r--r-- | kernel/satgen.cc | 27 | ||||
-rw-r--r-- | kernel/satgen.h | 1 | ||||
-rw-r--r-- | kernel/yosys.cc | 12 |
12 files changed, 244 insertions, 30 deletions
diff --git a/kernel/calc.cc b/kernel/calc.cc index 0865db526..32e8a49fe 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -609,6 +609,36 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len); } +RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) +{ + log_assert(arg2.size() == arg1.size()); + if (arg3[0] == State::S0) + return arg1; + else if (arg3[0] == State::S1) + return arg2; + + RTLIL::Const ret = arg1; + for (int i = 0; i < ret.size(); i++) + if (ret[i] != arg2[i]) + ret[i] = State::Sx; + return ret; +} + +RTLIL::Const RTLIL::const_pmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) +{ + if (arg3.is_fully_zero()) + return arg1; + + if (!arg3.is_onehot()) + return RTLIL::Const(State::Sx, arg1.size()); + + for (int i = 0; i < arg3.size(); i++) + if (arg3[i] == State::S1) + return RTLIL::Const(std::vector<RTLIL::State>(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size())); + + log_abort(); // unreachable +} + RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2) { std::vector<RTLIL::State> t = arg1.bits; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index d62ba1506..e617b4603 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -488,16 +488,10 @@ struct CellTypes static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr) { - if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) { - RTLIL::Const ret = arg1; - for (size_t i = 0; i < arg3.bits.size(); i++) - if (arg3.bits[i] == RTLIL::State::S1) { - std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size()); - ret = RTLIL::Const(bits); - } - return ret; - } - + if (cell->type.in(ID($mux), ID($_MUX_))) + return const_mux(arg1, arg2, arg3); + if (cell->type == ID($pmux)) + return const_pmux(arg1, arg2, arg3); if (cell->type == ID($_AOI3_)) return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1)); if (cell->type == ID($_OAI3_)) diff --git a/kernel/driver.cc b/kernel/driver.cc index 6d996783e..aa90802c9 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -202,6 +202,11 @@ extern char *yosys_argv0; extern char yosys_path[PATH_MAX]; }; #endif +#ifdef YOSYS_ENABLE_TCL +namespace Yosys { + extern int yosys_tcl_iterp_init(Tcl_Interp *interp); +}; +#endif int main(int argc, char **argv) { @@ -221,6 +226,7 @@ int main(int argc, char **argv) bool call_abort = false; bool timing_details = false; bool run_shell = true; + bool run_tcl_shell = false; bool mode_v = false; bool mode_q = false; @@ -284,6 +290,9 @@ int main(int argc, char **argv) printf("\n"); printf(" -c tcl_scriptfile\n"); printf(" execute the commands in the tcl script file (see 'help tcl' for details)\n"); + printf("\n"); + printf(" -C\n"); + printf(" enters TCL interatcive shell mode\n"); #endif printf("\n"); printf(" -p command\n"); @@ -358,7 +367,7 @@ int main(int argc, char **argv) } int opt; - while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:r:D:P:E:x:B:")) != -1) + while ((opt = getopt(argc, argv, "MXAQTVCSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:r:D:P:E:x:B:")) != -1) { switch (opt) { @@ -496,6 +505,9 @@ int main(int argc, char **argv) case 'B': perffile = optarg; break; + case 'C': + run_tcl_shell = true; + break; default: fprintf(stderr, "Run '%s -h' for help.\n", argv[0]); exit(1); @@ -570,10 +582,18 @@ int main(int argc, char **argv) for (auto it = passes_commands.begin(); it != passes_commands.end(); it++) run_pass(*it); - if (run_shell) - shell(yosys_design); - else - run_backend(output_filename, backend_command); + if (run_tcl_shell) { +#ifdef YOSYS_ENABLE_TCL + Tcl_Main(argc, argv, yosys_tcl_iterp_init); +#else + log_error("Can't exectue TCL shell: this version of yosys is not built with TCL support enabled.\n"); +#endif + } else { + if (run_shell) + shell(yosys_design); + else + run_backend(output_filename, backend_command); + } yosys_design->check(); for (auto it : saved_designs) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index b2e574b02..1b8043f9a 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -78,7 +78,18 @@ uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx); } uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx); } +static void normalize_brackets(std::string &str) +{ + for (auto &c : str) { + if (c == '<') + c = '['; + else if (c == '>') + c = ']'; + } +} + fstHandle FstData::getHandle(std::string name) { + normalize_brackets(name); if (name_to_handle.find(name) != name_to_handle.end()) return name_to_handle[name]; else @@ -120,6 +131,7 @@ void FstData::extractVarNames() var.is_reg = (fstVarType)h->u.var.typ == FST_VT_VCD_REG; var.name = remove_spaces(h->u.var.name); var.scope = fst_scope_name; + normalize_brackets(var.scope); var.width = h->u.var.length; vars.push_back(var); if (!var.is_alias) @@ -134,35 +146,34 @@ void FstData::extractVarNames() if (clean_name[0]=='\\') clean_name = clean_name.substr(1); size_t pos = clean_name.find_last_of("<"); - if (pos != std::string::npos) { + if (pos != std::string::npos && clean_name.back() == '>') { std::string mem_cell = clean_name.substr(0, pos); + normalize_brackets(mem_cell); std::string addr = clean_name.substr(pos+1); addr.pop_back(); // remove closing bracket char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 16); if (*endptr) { - log_warning("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; - name_to_handle[stringf("%s.%s[%d]",var.scope.c_str(),mem_cell.c_str(),mem_addr)] = h->u.var.handle; - continue; } } pos = clean_name.find_last_of("["); - if (pos != std::string::npos) { + if (pos != std::string::npos && clean_name.back() == ']') { std::string mem_cell = clean_name.substr(0, pos); + normalize_brackets(mem_cell); std::string addr = clean_name.substr(pos+1); addr.pop_back(); // remove closing bracket char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 10); if (*endptr) { - log_warning("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; - name_to_handle[stringf("%s.%s[%d]",var.scope.c_str(),mem_cell.c_str(),mem_addr)] = h->u.var.handle; - continue; } } + normalize_brackets(clean_name); name_to_handle[var.scope+"."+clean_name] = h->u.var.handle; break; } @@ -241,6 +252,7 @@ void FstData::reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t sta past_data = last_data; callback(last_time); } + past_data = last_data; callback(end_time); } diff --git a/kernel/log.cc b/kernel/log.cc index 4403dd0c7..af8c422b8 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -352,6 +352,9 @@ static void logv_error_with_prefix(const char *prefix, log_error_atexit(); YS_DEBUGTRAP_IF_DEBUGGING; + const char *e = getenv("YOSYS_ABORT_ON_LOG_ERROR"); + if (e && atoi(e)) + abort(); #ifdef EMSCRIPTEN log_files = backup_log_files; diff --git a/kernel/log.h b/kernel/log.h index 3bc9fd978..822816cb4 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -393,6 +393,11 @@ void log_dump_val_worker(RTLIL::IdString v); void log_dump_val_worker(RTLIL::SigSpec v); void log_dump_val_worker(RTLIL::State v); +template<typename K, typename T, typename OPS> static inline void log_dump_val_worker(dict<K, T, OPS> &v); +template<typename K, typename OPS> static inline void log_dump_val_worker(pool<K, OPS> &v); +template<typename K> static inline void log_dump_val_worker(std::vector<K> &v); +template<typename T> static inline void log_dump_val_worker(T *ptr); + template<typename K, typename T, typename OPS> static inline void log_dump_val_worker(dict<K, T, OPS> &v) { log("{"); @@ -419,6 +424,18 @@ static inline void log_dump_val_worker(pool<K, OPS> &v) { log(" }"); } +template<typename K> +static inline void log_dump_val_worker(std::vector<K> &v) { + log("{"); + bool first = true; + for (auto &it : v) { + log(first ? " " : ", "); + log_dump_val_worker(it); + first = false; + } + log(" }"); +} + template<typename T> static inline void log_dump_val_worker(T *ptr) { log("%p", ptr); } diff --git a/kernel/mem.cc b/kernel/mem.cc index e5e855ef7..ed01a0867 100644 --- a/kernel/mem.cc +++ b/kernel/mem.cc @@ -504,6 +504,7 @@ void Mem::check() { int mask = (1 << max_wide_log2) - 1; log_assert(!(start_offset & mask)); log_assert(!(size & mask)); + log_assert(width != 0); } namespace { diff --git a/kernel/register.cc b/kernel/register.cc index 226963fda..9449890b1 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -822,6 +822,100 @@ struct HelpPass : public Pass { fclose(f); } + void write_rst(std::string cmd, std::string title, std::string text) + { + FILE *f = fopen(stringf("docs/source/cmd/%s.rst", cmd.c_str()).c_str(), "wt"); + // make header + size_t char_len = cmd.length() + 3 + title.length(); + std::string title_line = "\n"; + title_line.insert(0, char_len, '='); + fprintf(f, "%s", title_line.c_str()); + fprintf(f, "%s - %s\n", cmd.c_str(), title.c_str()); + fprintf(f, "%s\n", title_line.c_str()); + fprintf(f, ".. raw:: latex\n\n \\begin{comment}\n\n"); + + // render html + fprintf(f, ":code:`yosys> help %s`\n", cmd.c_str()); + fprintf(f, "--------------------------------------------------------------------------------\n\n"); + fprintf(f, ".. container:: cmdref\n"); + std::stringstream ss; + std::string textcp = text; + ss << text; + bool IsUsage = true; + int blank_count = 0; + size_t def_strip_count = 0; + bool WasDefinition = false; + for (std::string line; std::getline(ss, line, '\n');) { + // find position of first non space character + std::size_t first_pos = line.find_first_not_of(" \t"); + std::size_t last_pos = line.find_last_not_of(" \t"); + if (first_pos == std::string::npos) { + // skip formatting empty lines + if (!WasDefinition) + fputc('\n', f); + blank_count += 1; + continue; + } + + // strip leading and trailing whitespace + std::string stripped_line = line.substr(first_pos, last_pos - first_pos +1); + bool IsDefinition = stripped_line[0] == '-'; + IsDefinition &= stripped_line[1] != ' ' && stripped_line[1] != '>'; + bool IsDedent = def_strip_count && first_pos <= def_strip_count; + bool IsIndent = first_pos == 2 || first_pos == 4; + if (cmd.compare(0, 7, "verific") == 0) + // verific.cc has strange and different formatting from the rest + IsIndent = false; + + // another usage block + bool NewUsage = stripped_line.find(cmd) == 0; + + if (IsUsage) { + if (stripped_line.compare(0, 4, "See ") == 0) { + // description refers to another function + fprintf(f, "\n %s\n", stripped_line.c_str()); + } else { + // usage should be the first line of help output + fprintf(f, "\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str()); + WasDefinition = true; + } + IsUsage = false; + } else if (IsIndent && NewUsage && (blank_count >= 2 || WasDefinition)) { + // another usage block + fprintf(f, "\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str()); + WasDefinition = true; + def_strip_count = 0; + } else if (IsIndent && IsDefinition && (blank_count || WasDefinition)) { + // format definition term + fprintf(f, "\n\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str()); + WasDefinition = true; + def_strip_count = first_pos; + } else { + if (IsDedent) { + fprintf(f, "\n\n ::\n"); + def_strip_count = first_pos; + } else if (WasDefinition) { + fprintf(f, " ::\n"); + WasDefinition = false; + } + fprintf(f, "\n %s", line.substr(def_strip_count, std::string::npos).c_str()); + } + + blank_count = 0; + } + fputc('\n', f); + + // render latex + fprintf(f, ".. raw:: latex\n\n \\end{comment}\n\n"); + fprintf(f, ".. only:: latex\n\n"); + fprintf(f, " ::\n\n"); + std::stringstream ss2; + ss2 << textcp; + for (std::string line; std::getline(ss2, line, '\n');) { + fprintf(f, " %s\n", line.c_str()); + } + fclose(f); + } void execute(std::vector<std::string> args, RTLIL::Design*) override { if (args.size() == 1) { @@ -882,6 +976,21 @@ struct HelpPass : public Pass { fclose(f); } // this option is undocumented as it is for internal use only + else if (args[1] == "-write-rst-command-reference-manual") { + for (auto &it : pass_register) { + std::ostringstream buf; + log_streams.push_back(&buf); + it.second->help(); + if (it.second->experimental_flag) { + log("\n"); + log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str()); + log("\n"); + } + log_streams.pop_back(); + write_rst(it.first, it.second->short_help, buf.str()); + } + } + // this option is undocumented as it is for internal use only else if (args[1] == "-write-web-command-reference-manual") { FILE *f = fopen("templates/cmd_index.in", "wt"); for (auto &it : pass_register) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 27ffdff1f..755abf534 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -500,6 +500,8 @@ namespace RTLIL RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); + RTLIL::Const const_mux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); + RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2); RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2); diff --git a/kernel/satgen.cc b/kernel/satgen.cc index 05eeca76e..2a1fd1711 100644 --- a/kernel/satgen.cc +++ b/kernel/satgen.cc @@ -1187,6 +1187,10 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep) if (timestep == 1) { initial_state.add((*sigmap)(cell->getPort(ID::Q))); + if (model_undef && def_formal) { + std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Q), timestep); + ez->assume(ez->NOT(ez->vec_reduce_or(undef_q))); + } } else { @@ -1254,13 +1258,18 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep) if (cell->type == ID($anyconst)) { - if (timestep < 2) + if (timestep < 2) { + if (model_undef && def_formal) { + std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep); + ez->assume(ez->NOT(ez->vec_reduce_or(undef_y))); + } return true; + } std::vector<int> d = importDefSigSpec(cell->getPort(ID::Y), timestep-1); std::vector<int> q = importDefSigSpec(cell->getPort(ID::Y), timestep); - std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q; + std::vector<int> qq = (model_undef && !def_formal) ? ez->vec_var(q.size()) : q; ez->assume(ez->vec_eq(d, qq)); if (model_undef) @@ -1268,14 +1277,24 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep) std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID::Y), timestep-1); std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Y), timestep); - ez->assume(ez->vec_eq(undef_d, undef_q)); - undefGating(q, qq, undef_q); + if (def_formal) { + for (auto &undef_q_bit : undef_q) + ez->SET(ez->CONST_FALSE, undef_q_bit); + } else { + ez->assume(ez->vec_eq(undef_d, undef_q)); + undefGating(q, qq, undef_q); + } } return true; } if (cell->type == ID($anyseq)) { + if (model_undef && def_formal) { + std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Y), timestep); + for (auto &undef_q_bit : undef_q) + ez->SET(ez->CONST_FALSE, undef_q_bit); + } return true; } diff --git a/kernel/satgen.h b/kernel/satgen.h index da2cec222..8a89ff9db 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -73,6 +73,7 @@ struct SatGen std::map<std::pair<std::string, int>, bool> initstates; bool ignore_div_by_zero; bool model_undef; + bool def_formal = false; SatGen(ezSAT *ez, SigMap *sigmap, std::string prefix = std::string()) : ez(ez), sigmap(sigmap), prefix(prefix), ignore_div_by_zero(false), model_undef(false) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index a56a066fe..4a22d0a7b 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -740,13 +740,19 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a return TCL_OK; } +int yosys_tcl_iterp_init(Tcl_Interp *interp) +{ + if (Tcl_Init(interp)!=TCL_OK) + log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno())); + Tcl_CreateCommand(interp, "yosys", tcl_yosys_cmd, NULL, NULL); + return TCL_OK ; +} + extern Tcl_Interp *yosys_get_tcl_interp() { if (yosys_tcl_interp == NULL) { yosys_tcl_interp = Tcl_CreateInterp(); - if (Tcl_Init(yosys_tcl_interp)!=TCL_OK) - log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno())); - Tcl_CreateCommand(yosys_tcl_interp, "yosys", tcl_yosys_cmd, NULL, NULL); + yosys_tcl_iterp_init(yosys_tcl_interp); } return yosys_tcl_interp; } |