Replies: 4 comments 9 replies
-
I would use imported C functions for this (BDPI in BSV). For BDPI, BSC generates proper code for both Bluesim and Verilog. In Verilog, it's implemented with Verilog's VPI. (However, you can give the new I assume the warning message you saw was this:
This is emitted in BSC's linking script for IVerilog. It's just a warning, because there are some uses that IVerilog fails to handle (which you'll notice immediately when you try to run), and newer IVerilog versions have fixes for some of them. I seem to recall that the situations which IVerilog didn't support are pure functions (which appear in Verilog continuous assignments); so as long as your imports are of type
Do you have a small example that I can run? The definition of
It would help if you can provide an executable example. I'm not sure if you've shown enough code for me to understand what you're doing. BSC doesn't preserve vectors in the output code. It inlines everything, which can cause the code to get large. This is possibly a scaling issue, when you're trying to do software-like things. And there may be enhancements (or bug fixes) that can improve the scaling. (There are probably also a lot of optimizations that can happen on the Bluesim generated code that we just haven't implemented yet, because it hasn't been a priority.) But I would suggest avoiding the problem by importing a C function. And if you run into scaling after that you can push any software-like processing inside the C function, instead of in the BH/BSV. For communication with a software process, we have imported C functions that communicate over pipes. I don't see a good example online, but there is an example inside the Flute repo: https://github.com/bluespec/Flute/blob/master/src_Testbench/Top/C_Imports.bsv#L144-L171 Flute is a CPU and the testbench in that repo supports connecting a GDB process to it, using GDB's remote connection capability (over a pipe). There's an intermediate C program that handles the complicated communication protocol with GDB and translates it into simple requests to the hardward. So, on the hardware side, there are C functions for getting requests (from the intermediary) and sending responses, which are of fixed sizes (64-bit request and 32-bit response). And there are imported functions for connecting and disconnecting (to the pipe). The C implementations for these functions are in the same directory, if you want to look. The hardware handles one request per clock cycle. The GDB connection can be used to load a program into memory, for example. This happens as a series of requests, which happens over many clock cycles. Your code snippet suggests that you want to send in 256 32-bit words at a time. I don't know what you're doing with that data -- if you're trying to parse that in one clock cycle, I could imagine it generating excessive hardware, and that would be something that I'd push into the C function. If you're just passing it to a method that takes an argument that large (for example, it's going on a really wide bus), then that's fine, but probably better to read it all with one C function call that returns the full size, rather than many reads of small sizes that have to be concatenated. And as a last resort, try doing things over multiple clock cycles.
I don't recall what
I don't recall, but I would expect maybe not. We definitely want BH to have the same features as BSV, it just hasn't been done yet. I note that there is a FYI, there is a way to embed code from one syntax in the other. I thought we had both directions, but maybe it's only one. I can't see anything for embedding BSV code in BH, off hand. But in BSV, you can use the attribute
I thought that we did the same for BSV in BH, but maybe not. |
Beta Was this translation helpful? Give feedback.
-
Regarding this one side question:
I got this down to a simple repro: In
In My bsc version is When I run it as pasted above, the output is |
Beta Was this translation helpful? Give feedback.
-
Another quick reply to one of your Qs:
For example, using a very similar program to the one above:
(I used The compilation times are very non-linear. I realize that all of those
I will try later this week with the BDPI-only approach and see if I can get it working in bluesim and verilog. Maybe that warning just scared me off too early. A fair number of my issues revolve around knowing how to invoke bsc via bazel to get all the right artifacts in the right places, but that's definitely not in scope of this forum. Thanks again for the advice! |
Beta Was this translation helpful? Give feedback.
-
A few things to report back:
The issue I was having was because the macos distribution was x86_64, but everything else on my machine is arm64, and it was causing linking issues. I was able to fix it by building my own bsc from source. Other issues I had were with confusion about where certain files needed to be. For the heck of it along the way, I tried Is there any way to squelch the warning?
But when I compile it it complains about the properties line saying:
I tried removing the properties lines, and it just fails further on:
|
Beta Was this translation helpful? Give feedback.
-
Context: I've been working on a library (in bs classic, if that matters) that enables co-simulation.
The idea is for the bluesim or verilog simulation to be in communication with software, (C++, Rust, Python, whatever) which provides stimulus and checking of results. I'd like it to be language agnostic.
The approach I am using is to lean on file IO primitives (which are pretty much universally present in any language), and use named pipes for the stimulus-to-dut and dut-to-stimulus communication. I've run into a number of complications, most of which I can work though, but one that seems to be biting me the most is on the file-reading side bluespec. Specifically, it seems that all I get is "$fgetc". (And $ungetc).
I'd like for the pipes to cary binary data. Conversion to and from (e.g.) hex, seems like an unneeded step.
Here is where I started. (
i
is the input type. It is the stimulus I am passing from stim to dut, using its Bits instance, i_bytes is the numeric type with the number of bytes being transmitted):The first issue right off the bat is that
replicateM $ fgetc stim_to_dut)
does not do what I would expect.It seems that it reads one byte from the pipe, and then replicates the byte. Not sure why.
But, thankfully, replacing it with
mapM (\_ -> $fgetc stim_to_dut) _
seems to get the job done.The next issue is that it seems that this approach results in extremely strange code generation.
If
i
is any sufficiently large type, e.g.Vector 256 (UInt 32)
, the compilation takes a very long time, and eventually fails with a "Stack space overflow".If I increase the stack space, or reduce the size of the vector, I can get it to pass that phase of the compilation. The Verilog simulation works fine, but the bluesim fails to compile because the c++ compiler gives "fatal error: bracket nesting level exceeded maximum of 256". Again, I can get around this with compiler flags, but it feels like I am basically forcing it down a path where it should not be going.
So, I decided to use
import "BDPI"...
(in BSV .. I couldn't find the bs-classic equivalent) to wrap the c read and write calls. The bsc docs seemed to suggest that it would do the required magic to make it work in verilog too (with vpi_wrapper_*{c,h} files, etc.), but when I went down that road, I got compiler warnings that it was "not implemented" or "not guaranteed to work" etc.. I was unable to get it to work.So finally, I decided to go with the
import "BDPI"...
for bluesim, andimport "BVI"
for verilog, and then usegenC
to determine which to implement. But since the BVI approach only imports modules, not tasks, I had to make it a bit more complex, and ran into subtle timing issues and ordering issues. (The order of the two $fopen calls is important, as is the order of the read vs write, and it proved to be difficult to make those assurances in verilog).I am about to start fresh and try again with the "BDPI + BVI" version hoping I can overcome my earlier issues.. but I get the sense that there must be an easier way.
So... a few questions:
replicateM $ fgetc stim_to_dut)
vsmapM (\_ -> $fgetc stim_to_dut) _
thing expected? Or is that a bug?mapM_ (\b -> $fwrite dut_to_stim "%c" b)
), but I expect I could write out the completeBit(TMul o_bytes 8)
thing if I wanted, right? Is there a reason $fread is not there?import "BDPI"
stuff? I'd prefer to avoid BSV if I can.Beta Was this translation helpful? Give feedback.
All reactions