diff --git a/lfs.c b/lfs.c index 03f33107..e266a0e6 100644 --- a/lfs.c +++ b/lfs.c @@ -1095,7 +1095,7 @@ static inline lfs_rtag_t lfs_rbyd_flip( return LFS_MKRALT_( lfs_rtag_isred(alt), !lfs_rtag_isgt(alt), - (lt+gt-1) - lfs_rtag_weight(alt)); + (lt+gt+1) - lfs_rtag_weight(alt)); // TODO } @@ -1227,6 +1227,9 @@ static lfs_srtag_t lfs_rbyd_lookup(lfs_t *lfs, const lfs_rbyd_t *rbyd, lfs_rtag_type2(alt), lfs_rtag_id(tag)); + printf("lt, gt = (%x, %x)\n", lt, gt); + printf("lookup %08x => %08x (raw %08x)\n", tag, tag_, alt); + // not what we're looking for? if (tag_ < tag) { return LFS_ERR_NOENT; @@ -1236,8 +1239,6 @@ static lfs_srtag_t lfs_rbyd_lookup(lfs_t *lfs, const lfs_rbyd_t *rbyd, *off = branch + delta; *size = jump; - printf("lt, gt = (%x, %x)\n", lt, gt); - printf("lookup %08x => %08x (raw %08x)\n", tag, tag_, alt); //return alt; // TODO adjust //return lt << 3; //return lfs_rtag_setid(alt, lt >> 12); @@ -1458,7 +1459,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, // queue of pending alts we can emulate rotations with lfs_rtag_t p_alts[3] = {0, 0, 0}; lfs_off_t p_jumps[3] = {0, 0, 0}; - lfs_rtag_t stump = 0; + lfs_rtag_t xylem = 0; // descend down tree, building alt pointers while (true) { @@ -1524,7 +1525,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, // } else { // lfs_rtag_t alt_ = p_alts[0]; // p_alts[0] = lfs_rtag_black(alt); -// p_jumps[0] = stump; +// p_jumps[0] = xylem; // // lfs_rbyd_trim(alt_, <, >); // lfs_rbyd_trim(alt, <, >); @@ -1535,9 +1536,13 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, // } // should've taken red alt? - if (lt < 0 || gt < 0) { - LFS_ASSERT(p_alts[0] && lfs_rtag_isred(p_alts[0])); + printf("lt,gt = (%x,%x)\n", lt, gt); + printf("p = %08x %d\n", p_alts[0], lfs_rtag_isred(p_alts[0])); + if (p_alts[0] + && lfs_rtag_isred(p_alts[0]) + && (lt < 0 || gt < 0)) { LFS_ASSERT(lfs_rtag_isblack(alt)); + printf("???\n"); if (lfs_rtag_parallel(alt, p_alts[0])) { printf("rflip parallel (%x,%x)\n", lt, gt); @@ -1560,6 +1565,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, lfs_rbyd_untrim(alt, <, >); lfs_rbyd_trim(p_alts[0], <, >); + printf("=> (%x, %x)\n", lt, gt); } @@ -1596,7 +1602,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, // off += delta; // // lfs_rbyd_trim(alt_, <, >); -// stump = branch_; +// xylem = branch_; // branch = jump_; // // } else if (p_alts[0] @@ -1621,7 +1627,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, // } // off += delta; // -// stump = branch_; +// xylem = branch_; // branch = jump_; // take black alt? @@ -1638,8 +1644,8 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, } off += delta; - lfs_rbyd_trim(lfs_rbyd_flip(alt, lt, gt), <, >); - stump = branch_; + lfs_rbyd_trim(p_alts[0], <, >); + xylem = branch_; branch = jump; // continue down current path @@ -1656,20 +1662,28 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, off += delta; lfs_rbyd_trim(alt, <, >); - stump = branch_; + xylem = branch_; } // found end of tree? } else { + // update the tag id + // TODO should this be a function? maybe see what create/delete need + // TODO alternatively can we do this a bit more directly here + lfs_rtag_t tag_ = LFS_MKRTAG_( + lfs_rtag_type1(alt), + lfs_rtag_type2(alt), + lfs_rtag_id(attr->tag)); + // split leaf? - if (alt != attr->tag) { + if (tag_ != attr->tag) { + // bias the weights so that lookups always find the + // next biggest tag lfs_rtag_t alt_; - if (lfs_rtag_weight(alt) < lfs_rtag_weight(attr->tag)) { - // bias the weights so that lookups always find the - // next biggest tag - alt_ = LFS_MKRALT(B, LT, lt+1 - ( - lfs_rtag_weight(attr->tag) - - lfs_rtag_weight(alt))); + if (lfs_rtag_weight(tag_) < lfs_rtag_weight(attr->tag)) { + alt_ = LFS_MKRALT(B, LT, lt+1 + + lfs_rtag_weight(tag_) + - lfs_rtag_weight(attr->tag)); } else { alt_ = LFS_MKRALT(B, GT, gt); } @@ -1684,7 +1698,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, } off += delta; - lfs_rbyd_p_red(p_alts, p_jumps); + //lfs_rbyd_p_red(p_alts, p_jumps); } // flush any pending alts diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index 048f7845..24d4d7a3 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -74,7 +74,7 @@ def tagrepr(tag, size, off=None): return 'alt%s%s x%x %s' % ( 'r' if type1 & 1 else 'b', 'gt' if type1 & 2 else 'lt', - tag >> 3, + tag & ~0x7, 'x%x' % (0xffffffff & (off-size)) if off is not None else '-%d' % off) diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index ef174a3e..a82078f1 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -1,9 +1,11 @@ # Test this inner rbyd data-structure +# test with a number of different erase values +defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] + [cases.test_rbyd_commit_fetch] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -43,7 +45,6 @@ code = ''' [cases.test_rbyd_multi_commit_fetch] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -84,7 +85,6 @@ code = ''' [cases.test_rbyd_commit_lookup] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -172,7 +172,6 @@ code = ''' # one way [cases.test_rbyd_multi_commit_lookup] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -260,7 +259,6 @@ code = ''' [cases.test_rbyd_bifoliate] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -312,7 +310,6 @@ code = ''' [cases.test_rbyd_bflips] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -366,7 +363,6 @@ code = ''' [cases.test_rbyd_trifoliate] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -381,7 +377,7 @@ code = ''' .erased = true, }; - // without a flip + // ignore a black edge // | LFS_MKRTAG(GSTATE, 3, 0); - // with a flip + // flip a black edge // >r // .-'| // | >b @@ -429,7 +425,6 @@ code = ''' [cases.test_rbyd_rflips] in = 'lfs.c' -defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -534,3 +529,128 @@ code = ''' lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 3, 0), &off, &size) => LFS_MKRTAG(GSTATE, 3, 0); ''' + +[cases.test_rbyd_quadrifoliate] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t rbyd_init = { + .block = 0, + .trunk = 0, + .noff = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + + // ignore a red edge and black edge + // | .----'| + // | 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(GSTATE, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, + LFS_MKRATTR(GSTATE, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, + LFS_MKRATTR(GSTATE, 3, 0, &(uint32_t){0xcccccccc}, 4, + LFS_MKRATTR(GSTATE, 4, 0, &(uint32_t){0xdddddddd}, 4, NULL))))) => 0; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_off_t off; + lfs_size_t size; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 1, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 2, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 3, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 3, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 4, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 4, 0); + + // ignore a red edge, flip a black edge + // y + // .-------'| .-'| + // r | >r + // .----'| => | .-'| => .--|-'| + // | b | | 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(GSTATE, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, + LFS_MKRATTR(GSTATE, 3, 0, &(uint32_t){0xbbbbbbbb}, 4, + LFS_MKRATTR(GSTATE, 4, 0, &(uint32_t){0xcccccccc}, 4, + LFS_MKRATTR(GSTATE, 2, 0, &(uint32_t){0xdddddddd}, 4, NULL))))) => 0; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 1, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 2, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 3, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 3, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 4, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 4, 0); + + // flip a red edge and black edge + // >y + // .-'| + // b + // .----'| => .--|-'| + // | b + // | .-'| .--|--|-'| + // 2 3 4 2 3 4 1 + rbyd = rbyd_init; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(GSTATE, 2, 0, &(uint32_t){0xaaaaaaaa}, 4, + LFS_MKRATTR(GSTATE, 3, 0, &(uint32_t){0xbbbbbbbb}, 4, + LFS_MKRATTR(GSTATE, 4, 0, &(uint32_t){0xcccccccc}, 4, + LFS_MKRATTR(GSTATE, 1, 0, &(uint32_t){0xdddddddd}, 4, NULL))))) => 0; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 1, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 2, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 3, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 3, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 4, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 4, 0); + + printf("-------------------------\n"); + // TODO this doesn't work since 2!<1? 4 2 3 1 should work consistently + // flip a red edge, ignore a black edge + // >y + // .-------'| + // r + // .-'| => | .-'| + // | >b | | 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(GSTATE, 4, 0, &(uint32_t){0xaaaaaaaa}, 4, + LFS_MKRATTR(GSTATE, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, + LFS_MKRATTR(GSTATE, 3, 0, &(uint32_t){0xcccccccc}, 4, + LFS_MKRATTR(GSTATE, 1, 0, &(uint32_t){0xdddddddd}, 4, NULL))))) => 0; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 1, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 2, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 3, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 3, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(GSTATE, 4, 0), &off, &size) + => LFS_MKRTAG(GSTATE, 4, 0); +'''