134 karma · joined June 28, 2023
Wouldn't it be more sensible to have one module for converting the AXI-Lite (I presume?) memory map interface to the specific input format of your processor, and then have the processor pull data from this adaptor when it needs it? That way still all handling of inputs is done in the same place.
Edit: maybe, what it comes down to is: Should the register bank be responsible for storing the state the compute unit is working on, or should the compute unit store that state itself? In my opinion, that responsibility lies with the compute unit. The compute unit shouldn't have to rely on the register bank not changing while its working.
I'm noting down this conetrace for the future though, seems like a useful tool, and they seem to be doing a closed beta of sorts.
Whereas for regular people, an upswing means nothing, whereas a downswing means job loss, mortgage rate hikes, etc.
The goal is to get consistent synthesis to 450MHz such that I can use a narrower 256-bit instead of a 512-bit interface, while maintaining full bandwidth. I've got it working at an FMax ranging 440-490MHz, though there's still some edge cases I need to hammer out.
I think improving the safety of hardware design is a noble goal, and certainly there is much that can be improved over Verilog & VHDL's incredibly brittle baseline.
Though for dynamic latency safety, my intuition tells me the problem space is undecidable. Sure one could prove the correctness of various kinds of dynamic latency pipelines, and as research progresses you'll include more and more such constructs, but it'll always remain possible to construct a correct but unprovable dynamic pipeline.
Given that, shouldn't we take a leaf out of Rust's book, and instead give the user tools to build abstractions which internally contain unprovable but correct black magic, yet on their interface provide a safe, static latency count.
Take for instance SUS' SlowState. It abstracts over an internal state, and the user provides a pipeline to update this internal state. Now, if we were to update the state twice, before the change has had time to propagate through the pipeline, that would be an error. SlowState prevents you from doing so by statically measuring the length of the update pipeline, and only allowing updates once it has cleared. Implementing SlowState requires some unsafe, but it can provide a safe interface upholding its requirement.
> We will edit su.c to prevent the overflow by maintaining a counter, i, and verifying it against the buffer size during the read loop. I initially attempted a fix using pointer arithmetic, but the 1973 C compiler didn’t like it, while it didn’t refuse the syntax, the code had no effect. I settled on a simpler index-based check instead.
I'm tooting my own horn with this, as I'm building my own language for doing the actual designing. It's called SUS.
Simple things look pretty much like C:
module add :
int#(FROM:-8, TO: 8) a,
int#(FROM: 2, TO: 20) b ->
int c {
c = a+b
}
It automatically compensates for pipelining registers you add, and allows you to use this pipelining information in the type system.It's a very young language, but me, a few of my colleagues, and some researchers in another university are already using it. Check it out => https://github.com/pc2/sus-compiler
This means that if I walk into a random croissant shop and buy a croissant, I don't subsequently have 2 days of food poisoning.
Arguably, healthier being the default is also good. The less I personally need to think about this, the more I can think about other more useful things.
Turns out, wrong train, going slightly the wrong way. But a guy walks up to me in the train, asks me where I'm going, and starts to help me get to where I need to go. He arranged a bunk for me, talked to the conductor for me, bought(!) another train to Agra for me, called hostels in Agra, etc etc. I've had multiple such encounters here in India, of people going so far out of their way to help me here, something you would honestly never see in my country Germany. It's like a strange incongruence, with one fraction of the population hell-bent on fleecing you for all you've got, and another that will go way further out of their way for you than you could ever imagine.
Yes, portability like that is a huge benefit, though I personally utilized it for that yet. I just use it as an error-tolerant frontend to my compiler.
As to how errors are reported, tree-sitter creates an ERROR or MISSING node when a particular subtree has invalid syntax. I've found that it never leaves a node in an invalid state, (so never would it create a binaryop(LeftNode(...), Op, ERROR) if RightNode is not optional. Instead it would create an ERROR for binaryop too. This allows you to safely unwrap known fields. ERROR nodes only really bunch up in repeat() and optional()s where you would implicity handle them.
For an example, I can only point you to my own use: https://github.com/pc2/sus-compiler
tree-sitter-sus has the grammar
sus-proc-macro has nice proc macros for dealing with it (kind!("binop"), field!("name"), etc)
src/flattening/parser.rs has conveniences like iterating over lists
and src/flattening/flatten.rs has the actual conversion from syntax tree to SUS IR
Instead, stick with std::hint::black_box for both inputs and outputs. Your benchmark will have no overhead from them, and you're benchmarking exactly what you intend. For low-level benchmarks, use repeats (again with std::hint::black_box on independent loops, or a proper microbenchmarking framework
Sadly, the simplicity benefits it touts over Mutexes simply don't pan out. You still have to have some structure around your critical section, it forces you to still contend with partially-updated intermediate values, which mutexes spare you from.
Likewise, the composition issue isn't more solved with STM than with Mutexes. Implementations that wish to support re-entrant transactions still have overhead over those that don't, similar to the overhead a reentrant_mutex has over a regular mutex.
My favourite solution to the many-reader few-writer scenario is the rarely-supported "Upgradeable Shared Mutex". Like parking_lot's RwLock (https://docs.rs/lock_api/0.4.14/lock_api/struct.RwLock.html#...)
With an Upgradeable Shared Mutex one can take a simple shared read lock, an exclusive write lock, or an upgradeble read lock. The upgradeable read lock can then - without unlocking - be upgraded to an exclusive lock once you've prepared the writes you wish to do, keeping the exclusive section as short as possible. To avoid deadlock, the upgradeable read lock can exist concurrently with simple read locks, but not other upgradeable locks.
async with mk_nursery() as nursery:
with os.fopen(...) as file:
nursery.start_soon(lambda: file.read())
The with block may have ended before the task starts...Wait, how exactly does one "abuse" MAID?
People being so deep in poverty and addiction that they opt for MAID as an option isn't a symptom that it's "too easy" to access it, but rather that _society_ is failing them. And when those people finally say "Well fuck this shit I'm out", we reply "That's not allowed". Disregarding that companies won't hire them, rent & housing are ridiculous, they''re not allowed to put their tents anywhere and when they get kicked out their tents & belongings are trashed instead of being given back.