Skip to content

Commit

Permalink
Merge branch 'origin/master' into krys/docs
Browse files Browse the repository at this point in the history
  • Loading branch information
KrystalDelusion committed Mar 17, 2024
2 parents 2832034 + 3231c1c commit d2bf5a8
Show file tree
Hide file tree
Showing 18 changed files with 640 additions and 77 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ body:
- macOS
- Windows
- BSD
- WebAssembly
multiple: true
validations:
required: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
steps:
- name: Install Dependencies
run: |
brew install bison flex gawk libffi pkg-config bash
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install bison flex gawk libffi pkg-config bash
- name: Runtime environment
shell: bash
Expand Down
23 changes: 22 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,30 @@
List of major changes and improvements between releases
=======================================================

Yosys 0.38 .. Yosys 0.39-dev
Yosys 0.39 .. Yosys 0.40-dev
--------------------------

Yosys 0.38 .. Yosys 0.39
--------------------------
* New commands and options
- Added option "-extra-map" to "synth" pass.
- Added option "-dont_use" to "dfflibmap" pass.
- Added option "-href" to "show" command.
- Added option "-noscopeinfo" to "flatten" pass.
- Added option "-scopename" to "flatten" pass.

* SystemVerilog
- Added support for packed multidimensional arrays.

* Various
- Added "$scopeinfo" cells to preserve information about
the hierarchy during flattening.
- Added sequential area output to "stat -liberty".
- Added ability to record/replay diagnostics in cxxrtl backend.

* Verific support
- Added attributes to module instantiation.

Yosys 0.37 .. Yosys 0.38
--------------------------
* New commands and options
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ LIBS += -lrt
endif
endif

YOSYS_VER := 0.38+113
YOSYS_VER := 0.39+4

# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
Expand All @@ -157,15 +157,15 @@ endif
OBJS = kernel/version_$(GIT_REV).o

bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 543faed.. | wc -l`/;" Makefile
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 0033808.. | wc -l`/;" Makefile

# set 'ABCREV = default' to use abc/ as it is
#
# Note: If you do ABC development, make sure that 'abc' in this directory
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
ABCREV = 896e5e7
ABCREV = 0cd90d0
ABCPULL = 1
ABCURL ?= https://github.com/YosysHQ/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
Expand Down
17 changes: 17 additions & 0 deletions backends/aiger/aiger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ struct AigerWriter
int initstate_ff = 0;

dict<SigBit, int> ywmap_clocks;
vector<Cell *> ywmap_asserts;
vector<Cell *> ywmap_assumes;

int mkgate(int a0, int a1)
{
Expand Down Expand Up @@ -269,6 +271,7 @@ struct AigerWriter
unused_bits.erase(A);
unused_bits.erase(EN);
asserts.push_back(make_pair(A, EN));
ywmap_asserts.push_back(cell);
continue;
}

Expand All @@ -279,6 +282,7 @@ struct AigerWriter
unused_bits.erase(A);
unused_bits.erase(EN);
assumes.push_back(make_pair(A, EN));
ywmap_assumes.push_back(cell);
continue;
}

Expand Down Expand Up @@ -852,6 +856,19 @@ struct AigerWriter
for (auto &it : init_lines)
json.value(it.second);
json.end_array();

json.name("asserts");
json.begin_array();
for (Cell *cell : ywmap_asserts)
json.value(witness_path(cell));
json.end_array();

json.name("assumes");
json.begin_array();
for (Cell *cell : ywmap_assumes)
json.value(witness_path(cell));
json.end_array();

json.end_object();
}

Expand Down
128 changes: 107 additions & 21 deletions backends/cxxrtl/runtime/cxxrtl/cxxrtl_replay.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,27 @@
// <file> ::= <file-header> <definitions> <sample>+
// <file-header> ::= 0x52585843 0x00004c54
// <definitions> ::= <packet-define>* <packet-end>
// <sample> ::= <packet-sample> <packet-change>* <packet-end>
// <sample> ::= <packet-sample> (<packet-change> | <packet-diag>)* <packet-end>
// <packet-define> ::= 0xc0000000 ...
// <packet-sample> ::= 0xc0000001 ...
// <packet-change> ::= 0x0??????? <chunk>+ | 0x1??????? <index> <chunk>+ | 0x2??????? | 0x3???????
// <chunk>, <index> ::= 0x????????
// <packet-diag> ::= <packet-break> | <packet-print> | <packet-assert> | <packet-assume>
// <packet-break> ::= 0xc0000010 <message> <source-location>
// <packet-print> ::= 0xc0000011 <message> <source-location>
// <packet-assert> ::= 0xc0000012 <message> <source-location>
// <packet-assume> ::= 0xc0000013 <message> <source-location>
// <packet-end> ::= 0xFFFFFFFF
//
// The replay log contains sample data, however, it does not cover the entire design. Rather, it only contains sample
// data for the subset of debug items containing _design state_: inputs and registers/latches. This keeps its size to
// a minimum, and recording speed to a maximum. The player samples any missing data by setting the design state items
// to the same values they had during recording, and re-evaluating the design.
//
// Packets for diagnostics (prints, breakpoints, assertions, and assumptions) are used solely for diagnostics emitted
// by the C++ testbench driving the simulation, and are not recorded while evaluating the design. (Diagnostics emitted
// by the RTL can be reconstructed at replay time, so recording them would be a waste of space.)
//
// Limits
// ------
//
Expand Down Expand Up @@ -109,6 +118,33 @@

namespace cxxrtl {

// A single diagnostic that can be manipulated as an object (including being written to and read from a file).
// This differs from the base CXXRTL interface, where diagnostics can only be emitted via a procedure call, and are
// not materialized as objects.
struct diagnostic {
// The `BREAK` flavor corresponds to a breakpoint, which is a diagnostic type that can currently only be emitted
// by the C++ testbench code.
enum flavor {
BREAK = 0,
PRINT = 1,
ASSERT = 2,
ASSUME = 3,
};

flavor type;
std::string message;
std::string location; // same format as the `src` attribute of `$print` or `$check` cell

diagnostic()
: type(BREAK) {}

diagnostic(flavor type, const std::string &message, const std::string &location)
: type(type), message(message), location(location) {}

diagnostic(flavor type, const std::string &message, const char *file, unsigned line)
: type(type), message(message), location(std::string(file) + ':' + std::to_string(line)) {}
};

// A spool stores CXXRTL design state changes in a file.
class spool {
public:
Expand All @@ -127,7 +163,7 @@ class spool {

static constexpr uint32_t PACKET_SAMPLE = 0xc0000001;
enum sample_flag : uint32_t {
EMPTY = 0,
EMPTY = 0,
INCREMENTAL = 1,
};

Expand All @@ -139,6 +175,9 @@ class spool {
static constexpr uint32_t PACKET_CHANGEL = 0x20000000/* | ident */;
static constexpr uint32_t PACKET_CHANGEH = 0x30000000/* | ident */;

static constexpr uint32_t PACKET_DIAGNOSTIC = 0xc0000010/* | diagnostic::flavor */;
static constexpr uint32_t DIAGNOSTIC_MASK = 0x0000000f;

static constexpr uint32_t PACKET_END = 0xffffffff;

// Writing spools.
Expand Down Expand Up @@ -281,6 +320,12 @@ class spool {
emit_word(data[offset]);
}

void write_diagnostic(const diagnostic &diagnostic) {
emit_word(PACKET_DIAGNOSTIC | diagnostic.type);
emit_string(diagnostic.message);
emit_string(diagnostic.location);
}

void write_end() {
emit_word(PACKET_END);
}
Expand Down Expand Up @@ -397,11 +442,16 @@ class spool {
return true;
}

bool read_change_header(uint32_t &header, ident_t &ident) {
bool read_header(uint32_t &header) {
header = absorb_word();
if (header == PACKET_END)
return false;
assert((header & ~(CHANGE_MASK | MAXIMUM_IDENT)) == 0);
return header != PACKET_END;
}

// This method must be separate from `read_change_data` because `chunks` and `depth` can only be looked up
// if `ident` is known.
bool read_change_ident(uint32_t header, ident_t &ident) {
if ((header & ~(CHANGE_MASK | MAXIMUM_IDENT)) != 0)
return false; // some other packet
ident = header & MAXIMUM_IDENT;
return true;
}
Expand All @@ -427,6 +477,18 @@ class spool {
for (size_t offset = 0; offset < chunks; offset++)
data[chunks * index + offset] = absorb_word();
}

bool read_diagnostic(uint32_t header, diagnostic &diagnostic) {
if ((header & ~DIAGNOSTIC_MASK) != PACKET_DIAGNOSTIC)
return false; // some other packet
uint32_t type = header & DIAGNOSTIC_MASK;
assert(type == diagnostic::BREAK || type == diagnostic::PRINT ||
type == diagnostic::ASSERT || type == diagnostic::ASSUME);
diagnostic.type = (diagnostic::flavor)type;
diagnostic.message = absorb_string();
diagnostic.location = absorb_string();
return true;
}
};

// Opening spools. For certain uses of the record/replay mechanism, two distinct open files (two open files, i.e.
Expand Down Expand Up @@ -584,6 +646,18 @@ class recorder {
return changed;
}

void record_diagnostic(const diagnostic &diagnostic) {
assert(streaming);

// Emit an incremental delta cycle per diagnostic to simplify the logic of the recorder. This is inefficient, but
// diagnostics should be rare enough that this inefficiency does not matter. If it turns out to be an issue, this
// code should be changed to accumulate diagnostics to a buffer that is flushed in `record_{complete,incremental}`
// and also in `advance_time` before the timestamp is changed. (Right now `advance_time` never writes to the spool.)
writer.write_sample(/*incremental=*/true, pointer++, timestamp);
writer.write_diagnostic(diagnostic);
writer.write_end();
}

void flush() {
writer.flush();
}
Expand Down Expand Up @@ -657,8 +731,9 @@ class player {
streaming = true;

// Establish the initial state of the design.
initialized = replay();
assert(initialized);
std::vector<diagnostic> diagnostics;
initialized = replay(&diagnostics);
assert(initialized && diagnostics.empty());
}

// Returns the pointer of the current sample.
Expand Down Expand Up @@ -690,8 +765,8 @@ class player {
// If this function returns `true`, then `current_pointer() == at_pointer`, and the module contains values that
// correspond to this pointer in the replay log. To obtain a valid pointer, call `current_pointer()`; while pointers
// are monotonically increasing for each consecutive sample, using arithmetic operations to create a new pointer is
// not allowed.
bool rewind_to(spool::pointer_t at_pointer) {
// not allowed. The `diagnostics` argument, if not `nullptr`, receives the diagnostics recorded in this sample.
bool rewind_to(spool::pointer_t at_pointer, std::vector<diagnostic> *diagnostics) {
assert(initialized);

// The pointers in the replay log start from one that is greater than `at_pointer`. In this case the pointer will
Expand All @@ -707,18 +782,21 @@ class player {
reader.rewind(position_it->second);

// Replay samples until eventually arriving to `at_pointer` or encountering end of file.
while(replay()) {
while(replay(diagnostics)) {
if (pointer == at_pointer)
return true;

if (diagnostics)
diagnostics->clear();
}
return false;
}

// If this function returns `true`, then `current_time() <= at_or_before_timestamp`, and the module contains values
// that correspond to `current_time()` in the replay log. If `current_time() == at_or_before_timestamp` and there
// are several consecutive samples with the same time, the module contains values that correspond to the first of
// these samples.
bool rewind_to_or_before(const time &at_or_before_timestamp) {
// these samples. The `diagnostics` argument, if not `nullptr`, receives the diagnostics recorded in this sample.
bool rewind_to_or_before(const time &at_or_before_timestamp, std::vector<diagnostic> *diagnostics) {
assert(initialized);

// The timestamps in the replay log start from one that is greater than `at_or_before_timestamp`. In this case
Expand All @@ -734,7 +812,7 @@ class player {
reader.rewind(position_it->second);

// Replay samples until eventually arriving to or past `at_or_before_timestamp` or encountering end of file.
while (replay()) {
while (replay(diagnostics)) {
if (timestamp == at_or_before_timestamp)
break;

Expand All @@ -743,14 +821,17 @@ class player {
break;
if (next_timestamp > at_or_before_timestamp)
break;

if (diagnostics)
diagnostics->clear();
}
return true;
}

// If this function returns `true`, then `current_pointer()` and `current_time()` are updated for the next sample
// and the module now contains values that correspond to that sample. If it returns `false`, there was no next sample
// to read.
bool replay() {
// to read. The `diagnostics` argument, if not `nullptr`, receives the diagnostics recorded in the next sample.
bool replay(std::vector<diagnostic> *diagnostics) {
assert(streaming);

bool incremental;
Expand All @@ -771,11 +852,16 @@ class player {
}

uint32_t header;
spool::ident_t ident;
variable var;
while (reader.read_change_header(header, ident)) {
variable &var = variables.at(ident);
reader.read_change_data(header, var.chunks, var.depth, var.curr);
while (reader.read_header(header)) {
spool::ident_t ident;
diagnostic diag;
if (reader.read_change_ident(header, ident)) {
variable &var = variables.at(ident);
reader.read_change_data(header, var.chunks, var.depth, var.curr);
} else if (reader.read_diagnostic(header, diag)) {
if (diagnostics)
diagnostics->push_back(diag);
} else assert(false && "Unrecognized packet header");
}
return true;
}
Expand Down
13 changes: 12 additions & 1 deletion backends/smt2/smt2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,18 @@ struct Smt2Worker

string name_a = get_bool(cell->getPort(ID::A));
string name_en = get_bool(cell->getPort(ID::EN));
if (cell->name[0] == '$' && cell->attributes.count(ID::src))
bool private_name = cell->name[0] == '$';

if (!private_name && cell->has_attribute(ID::hdlname)) {
for (auto const &part : cell->get_hdlname_attribute()) {
if (part == "_witness_") {
private_name = true;
break;
}
}
}

if (private_name && cell->attributes.count(ID::src))
decls.push_back(stringf("; yosys-smt2-%s %d %s %s\n", cell->type.c_str() + 1, id, get_id(cell), cell->attributes.at(ID::src).decode_string().c_str()));
else
decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, get_id(cell)));
Expand Down
Loading

0 comments on commit d2bf5a8

Please sign in to comment.