Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$print internal cell, for formatting tasks #3721

Merged
merged 41 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
73aac97
read_verilog: set location of AST_TCALL.
whitequark Nov 29, 2020
6ad9246
kernel: add format string helpers, `fmt`.
whitequark Nov 29, 2020
9f494ae
ast: use new format string helpers.
whitequark Nov 29, 2020
5d9e193
ast: translate $display/$write tasks in always blocks to new $print c…
whitequark Nov 29, 2020
5c4765a
clean: keep $print cells, since they have unmodelled side effects.
whitequark Nov 29, 2020
a8da8db
write_verilog: translate $print cells to $write tasks in always blocks.
whitequark Nov 29, 2020
77aa0bb
fmt: add tests for Yosys evaluation of format expressions.
whitequark Dec 5, 2020
68741b2
fmt: add tests for Verilog round trip of format expressions.
whitequark Dec 6, 2020
31815e0
fmt: ensure test exits on fail
charlottia Jun 28, 2023
8dacdb8
celltypes: add `$print`
charlottia Jun 28, 2023
97eb03e
fmt: tests completing again
charlottia Jun 28, 2023
fbd60b2
fmt: don't overrun fmt string buffer
charlottia Jun 28, 2023
12ce4f5
fmt: fix another overrun
charlottia Jun 28, 2023
afcee67
fmt: correct parsing of {{ and }} for brace literals
charlottia Jun 28, 2023
d60cfbb
docs: first pass $print documentation
charlottia Jun 28, 2023
45fdba2
fmt: function name typo
charlottia Jun 28, 2023
4fe2e46
fmt: handle part with unspecified padding in `emit_rtlil`
charlottia Jun 28, 2023
6993260
docs: elaborate $print documentation
charlottia Jun 28, 2023
4d061dd
cxxrtl: first pass of $print impl
charlottia Jun 28, 2023
d40471c
tests: test cxxrtl against iverilog (and uncover bug!)
charlottia Jun 28, 2023
1b7e70b
cxxrtl: don't use signed divide with unsigned/pos values
charlottia Jun 28, 2023
dfe5b47
fmt: %t/$time support
charlottia Jun 28, 2023
41f2c17
fmt: rudimentary %m support (= %l)
charlottia Jun 28, 2023
5266d30
docs: document simulation time format specifiers
charlottia Jun 28, 2023
67623fc
fmt: format %t consistently at initial
charlottia Jun 28, 2023
ef1eed5
fmt: fuzz, fix (remove extraneous + incorrect fill)
charlottia Jun 28, 2023
796459e
fmt: fuzz, remove some unnecessary busywork
charlottia Jun 28, 2023
6604dd4
fmt: merge fuzzers since we don't rely on BigInteger logic
charlottia Jun 28, 2023
f740d96
cxxrtl: remove unused signedDivideWithRemainder
charlottia Jun 28, 2023
4520c6a
cxxrtl: add "-print-output" option, test in fmt
charlottia Jun 28, 2023
eb028fa
cxxrtl: restrict -print-output to cout, cerr
charlottia Jun 28, 2023
815f0f1
simlib: blackbox `$print` cell
charlottia Jun 28, 2023
5b8d590
tests: CXX may be e.g. gcc, so use CC and link stdc++ explicitly
charlottia Jun 28, 2023
0fc3daa
tests: -std=c++11 not optional
charlottia Jun 28, 2023
de3b689
fmt: remove lzero by lowering during Verilog parse
charlottia Jun 28, 2023
79be530
cxxrtl: WIP: adjust comb display cells to only fire on change
charlottia Jun 28, 2023
aa95736
cxxrtl: store comb $print cell last EN/ARGS in module
charlottia Jun 28, 2023
3040b1b
ast: add `PRIORITY` to `$print` cells
charlottia Jun 28, 2023
18c2016
verilog_backend: emit sync `$print` cells with same triggers together
charlottia Jun 28, 2023
cbd0ed2
cxxrtl_backend: respect sync `$print` priority
charlottia Jun 28, 2023
76d7d55
cxxrtl_backend: move sync $print grouping out of dump into analyze
charlottia Jun 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -652,12 +652,7 @@ $(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd_capi.h))

OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o
OBJS += kernel/binding.o
ifeq ($(ENABLE_ABC),1)
ifneq ($(ABCEXTERNAL),)
kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
endif
endif
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o
ifeq ($(ENABLE_ZLIB),1)
OBJS += kernel/fstdata.o
endif
Expand All @@ -669,6 +664,11 @@ endif

kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
ifeq ($(ENABLE_ABC),1)
ifneq ($(ABCEXTERNAL),)
kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
endif
endif

OBJS += libs/bigint/BigIntegerAlgorithms.o libs/bigint/BigInteger.o libs/bigint/BigIntegerUtils.o
OBJS += libs/bigint/BigUnsigned.o libs/bigint/BigUnsignedInABase.o
Expand Down Expand Up @@ -882,6 +882,7 @@ endif
+cd tests/memfile && bash run-test.sh
+cd tests/verilog && bash run-test.sh
+cd tests/xprop && bash run-test.sh $(SEEDOPT)
+cd tests/fmt && bash run-test.sh
@echo ""
@echo " Passed \"make test\"."
@echo ""
Expand Down
182 changes: 182 additions & 0 deletions backends/cxxrtl/cxxrtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,14 @@ struct value : public expr_base<value<Bits>> {
return count;
}

size_t chunks_used() const {
for (size_t n = chunks; n > 0; n--) {
if (data[n - 1] != 0)
return n;
}
return 0;
}

template<bool Invert, bool CarryIn>
std::pair<value<Bits>, bool /*CarryOut*/> alu(const value<Bits> &other) const {
value<Bits> result;
Expand Down Expand Up @@ -575,6 +583,84 @@ struct value : public expr_base<value<Bits>> {
result.data[result.chunks - 1] &= result.msb_mask;
return result;
}

// parallel to BigUnsigned::divideWithRemainder; quotient is stored in q,
// *this is left with the remainder. See that function for commentary describing
// how/why this works.
void divideWithRemainder(const value<Bits> &b, value<Bits> &q) {
assert(this != &q);

if (this == &b || &q == &b) {
value<Bits> tmpB(b);
divideWithRemainder(tmpB, q);
return;
}

q = value<Bits> {0u};

size_t blen = b.chunks_used();
if (blen == 0) {
return;
}

size_t len = chunks_used();
if (len < blen) {
return;
}

size_t i, j, k;
size_t i2;
chunk_t temp;
bool borrowIn, borrowOut;

size_t origLen = len;
len++;
chunk::type blk[len];
std::copy(data, data + origLen, blk);
blk[origLen] = 0;
chunk::type subtractBuf[len];
std::fill(subtractBuf, subtractBuf + len, 0);

size_t qlen = origLen - blen + 1;

i = qlen;
while (i > 0) {
i--;
i2 = chunk::bits;
while (i2 > 0) {
i2--;
for (j = 0, k = i, borrowIn = false; j <= blen; j++, k++) {
temp = blk[k] - getShiftedBlock(b, j, i2);
borrowOut = (temp > blk[k]);
if (borrowIn) {
borrowOut |= (temp == 0);
temp--;
}
subtractBuf[k] = temp;
borrowIn = borrowOut;
}
for (; k < origLen && borrowIn; k++) {
borrowIn = (blk[k] == 0);
subtractBuf[k] = blk[k] - 1;
}
if (!borrowIn) {
q.data[i] |= (chunk::type(1) << i2);
while (k > i) {
k--;
blk[k] = subtractBuf[k];
}
}
}
}

std::copy(blk, blk + origLen, data);
}

static chunk::type getShiftedBlock(const value<Bits> &num, size_t x, size_t y) {
chunk::type part1 = (x == 0 || y == 0) ? 0 : (num.data[x - 1] >> (chunk::bits - y));
chunk::type part2 = (x == num.chunks) ? 0 : (num.data[x] << y);
return part1 | part2;
}
};

// Expression template for a slice, usable as lvalue or rvalue, and composable with other expression templates here.
Expand Down Expand Up @@ -707,6 +793,99 @@ std::ostream &operator<<(std::ostream &os, const value<Bits> &val) {
return os;
}

template<size_t Bits>
struct value_formatted {
const value<Bits> &val;
bool character;
bool justify_left;
char padding;
int width;
int base;
bool signed_;
bool plus;

value_formatted(const value<Bits> &val, bool character, bool justify_left, char padding, int width, int base, bool signed_, bool plus) :
val(val), character(character), justify_left(justify_left), padding(padding), width(width), base(base), signed_(signed_), plus(plus) {}
value_formatted(const value_formatted<Bits> &) = delete;
value_formatted<Bits> &operator=(const value_formatted<Bits> &rhs) = delete;
};

template<size_t Bits>
std::ostream &operator<<(std::ostream &os, const value_formatted<Bits> &vf)
{
value<Bits> val = vf.val;

std::string buf;

// We might want to replace some of these bit() calls with direct
// chunk access if it turns out to be slow enough to matter.

if (!vf.character) {
size_t width = Bits;
if (vf.base != 10) {
width = 0;
for (size_t index = 0; index < Bits; index++)
if (val.bit(index))
width = index + 1;
}

if (vf.base == 2) {
for (size_t i = width; i > 0; i--)
buf += (val.bit(i - 1) ? '1' : '0');
} else if (vf.base == 8 || vf.base == 16) {
size_t step = (vf.base == 16) ? 4 : 3;
for (size_t index = 0; index < width; index += step) {
uint8_t value = val.bit(index) | (val.bit(index + 1) << 1) | (val.bit(index + 2) << 2);
if (step == 4)
value |= val.bit(index + 3) << 3;
buf += "0123456789abcdef"[value];
}
std::reverse(buf.begin(), buf.end());
} else if (vf.base == 10) {
bool negative = vf.signed_ && val.is_neg();
if (negative)
val = val.neg();
if (val.is_zero())
buf += '0';
while (!val.is_zero()) {
value<Bits> quotient;
val.divideWithRemainder(value<Bits>{10u}, quotient);
buf += '0' + val.template trunc<(Bits > 4 ? 4 : Bits)>().val().template get<uint8_t>();
val = quotient;
}
if (negative || vf.plus)
buf += negative ? '-' : '+';
std::reverse(buf.begin(), buf.end());
} else assert(false);
} else {
buf.reserve(Bits/8);
for (int i = 0; i < Bits; i += 8) {
char ch = 0;
for (int j = 0; j < 8 && i + j < int(Bits); j++)
if (val.bit(i + j))
ch |= 1 << j;
if (ch != 0)
buf.append({ch});
}
std::reverse(buf.begin(), buf.end());
}

assert(vf.width == 0 || vf.padding != '\0');
if (!vf.justify_left && buf.size() < vf.width) {
size_t pad_width = vf.width - buf.size();
if (vf.padding == '0' && (buf.front() == '+' || buf.front() == '-')) {
os << buf.front();
buf.erase(0, 1);
}
os << std::string(pad_width, vf.padding);
}
os << buf;
if (vf.justify_left && buf.size() < vf.width)
os << std::string(vf.width - buf.size(), vf.padding);

return os;
}

template<size_t Bits>
struct wire {
static constexpr size_t bits = Bits;
Expand Down Expand Up @@ -1091,7 +1270,10 @@ struct module {
virtual bool eval() = 0;
virtual bool commit() = 0;

unsigned int steps = 0;

size_t step() {
++steps;
size_t deltas = 0;
bool converged = false;
do {
Expand Down
Loading
Loading